零基础学C++之进阶篇三
零基础学C++之进阶篇三
类和对象
类是对象的实现,面向对象中的类是抽象概念,而类是程序开始过程中定义一个对象,用类定义对象可以是现实生活中的真实对象,也可以是从现实生活中抽象的对象。
c++类
类概述
面向对象的对象需要通过定义类来声明,类是一个新的数据类型,它和结构体有些相似,是由不同数据类型组合的集合体,但类要比结构体增加了操作数据的行为,这个行为就是函数。
类的声明与定义
类的声明格式如下:
class 类名标识符
{
[public:]
[数据成员的声明]
[成员函数的声明]
[private:]
[数据成员的声明]
[成员函数的声明]
[protected:]
[数据成员的声明]
[成员函数的声明]
};
类的声明格式说明如下:
- class是定义类结构体的关键字,大括号内被称为类体或类空间;
- 类名标识符指定的就是类名,类名就是一个新的数据类型,通过类名可以声明对象;
- 类的成员有函数和数据两种类型;
- 大括号内是定义和声明类成员的地方,关键字public、private、protected是类成员访问的修饰符。
类中的数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是对象,另一个类的对象可以作为该类的成员,但是自身类的对象不可以作为该类的成员,而自身类的指针或引用又可以作为该类的成员。
class CPerson
{
int m_index;
char m_name[25];
short m_age;
double m_salary;
short getAge();
int setAge(short age);
int getIndex();
int setIndex(int index);
char* getName();
int setName(char age[25]);
double getSalary();
int setSalary(double salary);
}
类的实现
第一种方法:将类的成员函数都定义在类体内。
第二种方法:将类体内的成员函数的实现放在类体外,但如果类成员定义在类体外,需要用到域运算符“::”,放在类体内和类体外的效果是一样的。
对象的声明
定义一个新类后,就可以通过类名来声明一个对象,声明的形式如下:
类名 对象名表;
对象声明之后需要引用其成员,c++提供了两种引用方式:
(1)成员引用方式
对象名.成员名;
对象名.成员函数(参数列表);
(2)对象指针方式
对象指针名->数据成员
*(对象指针名).数据成员
对象指针名->成员函数(参数列表)
*(对象指针名).成员函数(参数列表)
构造函数
构造函数概述
在类的实例进入其作用域时,也就是建立一个对象,构造函数就会被调用,进行一些初始化工作,例如对数据成员进行赋、设置类的属性等,构造函数可以带有参数。
实例01 构造函数的使用
#include <iostream>
using namespace std;
class Cperson
{
public:
Cperson();
Cperson(int index,short age,double salary);
int m_index;
short m_age;
double m_salary;
int getIndex();
};
Cperson::Cperson()
{
m_index=0;
m_age=10;
m_salary=1000;
}
Cperson::Cperson(int index,short age,double salary)
{
m_index = index;
m_age=age;
m_salary=salary;
}
int getIndex()
{
return m_index;
}
void main()
{
Cperson p1;
cout << "m_index is: " << p1.getIndex() << endl;
Cperson p2(1,20,1000);
cout << "m_index is: " << p2.getIndex() << endl;
}
复制构造函数
在开发程序中可能需要保存对象副本,以便在后面执行的过程中恢复对象的状态,复制构造函数是编译器调用来完成一些基于同一类的其他对象的构建及初始化,其唯一的形参必须是引用。
实例02 复制构造函数的使用
在头文件person.h中声明和定义类:
class Cperson
{
public:
Cperson(int index,short age,double salary);
Cperson(Cperson ©Person);
int m_index;
short m_age;
double m_salary;
int getIndex();
short getAge();
double getSalary();
}
Cperson::Cperson(int index,short age,double salary)
{
m_index = index;
m_age = age;
m_salary = salary;
}
Cperson::Cperson(Cperson ©Person)
{
m_index = copyPerson.m_index;
m_age = copyPerson.m_age;
m_salary = copyPerson.m_salary;
}
int getIndex()
{
return m_index;
}
short getAge()
{
return m_age;
}
double getSalary()
{
return m_salary;
}
在主程序文件中实现类对象的调用:
#include <iostream>
#include <person.h>
using namespace std;
void main()
{
Cperson p1(20,30,1000);
Cperson p2(p1);
cout << "p1.m_index=" << p1.getIndex() << endl;
cout << "p1.m_age=" << p1.getAge() << endl;
cout << "p1.m_salary=" << p1.getSalary() << endl;
cout << "p2.m_index=" << p2.getIndex() << endl;
cout << "p2.m_age=" << p2.getAge() << endl;
cout << "p2.m_salary=" << p2.getSalary() << endl;
}
析构函数
构造函数和析构函数是类体定义中比较特殊的两个成员函数,它们都没有返回值,构造函数名标识符和类名标识符相同,析构函数名标识符在类名标识符前面加“~”符号。
构造函数主要是用来在对象创建时,给对象中的一些数据成员赋值,主要目的就是初始化对象,析构函数的功能是用来释放一个对象,在对象删除前,用来做一些清理工作,它与构造函数的功能正好相反。
使用析构函数注意事项:
- 一个类中只能定义一个析构函数
- 析构函数不能重载
- 构造函数和析构函数不能使用return语句返回值,不能加上关键字void。
类成员
访问类成员
类的三大特点之中包括“封装性”,封装在类里面的数据可以设置成对外可见或不可见。通过关键字public、private、protected可以设置类中数据成员对外是否可见,也就是其他类是否可以访问该数据成员。public区域的类成员可以在类作用域外被访问,而private区域和protected区域只能在类作用域内被访问。
- public属性的成员对外可见,对内可见
- private属性的成员对外不可见,对内可见
- protected属性的成员对外不可见,对内可见,且对派生类可见
如果在类定义时没有加任何关键字,默认状态类成员都在private区域。
内联成员函数
在定义函数时,可以使用inline关键字将函数定义为内联函数,在定义类的成员函数时,也可以使用inline关键字将成员函数定义为内联成员函数。
静态类成员
静态成员是在类成员定义前使用static关键字标识。如果将类成员定义为静态成员,则允许类名直接访问。在定义静态成员是,通常需要在类体外部对静态成员进行初始化。
在一个类中,静态数据成员是被所有的类对象所共享的,这就意味着无论定义多少个类对象,类的静态数据成员只有一份,同时如果某一个对象修改了静态数据成员,其他对象的静态成员也将改变。
- 静态数据成员可以是当前类的类型,而其他数据成员只能是当前类的指针或应用类型;
- 静态数据成员可以作为成员函数的默认参数
定义类的静态成员函数与定义普通的成员函数类似,只需在成员函数前添加static关键字即可。
static void fun();
- 类的静态成员函数只能访问类的静态数据成员,而不能访问普通的数据成员。
- 静态成员函数不能定义为const成员函数,即静态成员函数末尾不能使用const关键字
嵌套类
C++语言允许在一个类中定义另一个类,这被称之为嵌套类:
#define MAXLEN 128
class List
{
public:
class Node
{
friend class List;
private:
int m_tag;
public:
char m_name[MAXLEN];
};
public:
Node m_node;
void setNodeName(const char* name)
{
if(name != NULL)
{
strcpy(m_node.m_name,name);
}
}
void setNodeTag(int tag)
{
m_node.m_tag = tag;
}
};
局部类
类的定义可以放在头文件中,也可以放在源文件中,还可以将类的定义放在函数中,这样的类被称之为局部类,局部类在函数之外是不能被访问的。
void localClass()
{
class Book
{
private:
int m_pages;
public:
void setPage(int page)
{
if(m_pages!=page)
m_pages=page;
}
int getPages()
{
return m_pages;
}
};
Book book;
book.setPage(300);
cout << book.getPages() << endl;
}
友元
友元概述
友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,在说明时前面加上关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。
使用friend关键字可以让特定的函数或者别的类的所有成员函数对私有数据成员进行读写,这既可以保持数据的私有性,又能够使特定的类或函数直接访问私有数据。
友元类
对于类的私有方法,只能在该类中允许访问,其他类是不能访问的。C++语言提供了友元类和友元方法来实现访问其他私有成员。
class Item
{
private:
char m_name[128];
void outputName()
{
printf("%s\n",m_name);
}
public:
friend class List;
void setItemName(const char* name)
{
if(name != NULL)
strcpy(m_name,name);
}
Item()
{
memset(m_name,0,128);
}
};
class List
{
private:
Item m_item;
public:
void outputItem();
};
void List::outputItem()
{
m_Item.setItemName("beijing");
m_Item.outputName();
}
在定义Item类时,使用friend关键字将List类定义为Item类的友元,这样List类中的所有方法都可以访问Item类中的私有成员。
友元方法
实例03 友元方法的使用
class Item;
class List
{
private:
Item *m_item;
public:
List();
~List();
void outputItem();
};
class Item
{
friend void List::outputItem(); //声明友元函数
private:
char m_name[128];
void outputName()
{
printf("%s\n",m_name);
}
public:
void setItemName(const char* name)
{
if(name!=NULL)
strcpy(m_name,name);
}
Item()
{
memset(m_name,0,128);
}
};
void List::outputItem()
{
m_item->setItemName("beijing");
m_item->outputName();
}
List::List()
{
m_item = new Item();
}
List::~List()
{
delet m_item;
m_item = NULL;
}
int main(int argc,char* argv[])
{
List list;
list.outputItem();
return 0;
}
在定义Item类时,使用friend关键字将List类的outputItem方法设置为友元函数,在List类的outputItem方法中访问了Item类的私有方法outputName。
命名空间
定义命名空间
在一个应用程序中的多个文件中可能会存在同名的全局对象,这样会导致应用程序的链接错误。使用命名空间是消除命名冲突的最佳方式。namespace是定义命名空间的关键字。
使用命名空间
命名空间的定义格式为:
namespace 名称
{
常量、变量、函数等对象的定义;
}
命名空间定义完成后,使用作用域限定符“::”来引用空间中的成员。引用空间成员的一般形式是:
命名空间名称::成员;
另一种引用命名空间中成员的方法,就是使用using namespace语句,一般形式为:
using namespace 命名空间名称;