构造函数:用以对类中数据成员进行初始化
系统会自动生成默认构造函数(参数为空),但是若手动定义了带参的构造函数,会自动覆盖默认构造函数时若需要调用默认构造函数进行实例化,需要手动定义一个不带参的构造函数
初始化列表:可通过初始化列表的方式对类数据成员进行初始化,如定义初始化列表:User():sId(0001),sSex(1)
继承基类时在派生类中调用基类的构造函数,对基类进行初始化,实际上就是初始化列表。
构造函数可以只在类体内声明,在类体外定义,且声明时不需要初始化列表,在定义时需要给出初始化列表(若有)。
有两种情况需要初始化列表:
- 数据成员中有常量成员:const int Id;
- 数据成员中有子对象,在类中包含另一个类对象:Group group1;
因为构造函数的执行顺序如下:
- 分配内存
- 初始化成员列表
- 执行构造函数
常量成员不能放在构造函数中:常量成员声明后无法修改,只能放在初始化列表中;
子对象:定义类对象首先要分配内存,如果包含另外的类对象,也需要为其分配内存,所以另外的类对象初始化要先于构造函数执行;
类的数据成员与成员函数是分开存放的,数据成员存放堆栈区,成员函数存放在代码区,成员函数通过this指针访问其自身对象
静态成员:
静态成员存放在静态全局区,与类实际上没有太大的关系。静态成员生存期为整个程序运行期,进程结束才释放!
静态成员需要在类体外定义(已在构造函数中初始化)或者初始化才能使用。
静态与非静态的相互访问:
经测试,构造函数也可以初始化静态成员,当然,其他的成员函数也可以操作静态成会员。
但是静态成员函数要想访问非静态成员,需要特殊处理:传递具体的类对象给静态成员函数,再通过该类对象访问非静态成员。
常成员函数:若一个成员函数用const修饰,则不允许修改内部成员,相当于对内部this指针加了const修饰,不能通过this->id = ...修改值。
析构函数:析构函数的作用并不是删除对象,而是在撤销对象占用的内存空间前进行一些清理工作。
系统会自动生成函数体为空的析构函数。
用途:在有内部指针的时候就要使用析构函数防止内存泄漏。
对于一般对象,如User user;出作用域时会自动执行析构函数
但对于动态分配的对象:User user = new user;即使出了作用域,也不会自动执行析构函数,必须手动进行delete user,才能调用析构函数。
static局部对象在函数调用结束时并不释放,也不调用析构函数。只有在main函数结束或执行exit语句,才调用static对象析构函数
析构函数同样可以定义在类体外,函数声明在类体内部;
析构函数执行顺序:
对于同类型对象,先构造的后析构,后构造的先析构。
原因:因为对象是存在于堆栈中,先进后出。
1 class CMyClass 2 { 3 public: 4 CMyClass():iNo(0) 5 {} 6 CMyClass(int i):iNo(i) 7 { 8 this->iId = i; 9 CMyClass(); 10 } 11 public: 12 int iId; 13 const int iNo; 14 };
构造函数:在建立对象时自动执行构造函数
CMyClass myObject; //自动执行构造函数
有参构造函数:
CMyClass myObject(1);//自动执行构造函数
一个构造函数中也可以手动调用另一个构造函数,但是若被调用的构造函数声明时带有初始化参数列表,但是参数初始化列表此时不会执行
只有系统自动调用时才会执行参数初始化列表
如上例,在CMyClass(int i) 中调用MyClass(),不会执行初始化列表iNo(0);
调用构造函数和析构函数的顺序:
1、全局对象:构造函数在文件中的所有函数执行之前调用,main函数执行完毕或调用exit时执行析构函数
2、静态局部:在程序中第一此调用此静态局部对象所在的函数时调用构造函数一次,调用结束后并不释放,main函数执行完毕或调用exit时执行析构函数
3、局部自动对象:在建立对象时调用其构造函数,其所在函数执行完毕对象释放时,调用其析构函数