构造函数
数据成员多为私有的,要对他们进行初始化,必须使用一个共有函数进行,同时这个函数应该在且仅在定义对象时自动执行一次。
1.构造函数和类的名字是一样的,且无返回值(没有返回值不是指返回值为void)。
2.对象构造时(实例化)系统自动调用。
3.构造函数在类外也可以定义(类名::)。
4.若定义中没有给出构造函数,则编译器自动生成一个缺省的构造函数,若自己定义构造函数,系统则不会自动生成。
5.无参构造函数和全缺省值的构造函数都认为是缺省构造函数,且缺省构造函数只能有一个。
6.构造函数可以重载,说明中可以有多个构造函数,它们由不同的参数表区分,系统在自动调用时按一般函数重载规则选一个执行。
ps:构造函数的三个作用
1.构造对象
2.初始化对象
3.类型转换
析构函数
与构造函数相反的过程
1.在类名前加~(可以理解为构造函数取反)。
2.无参数无返回值。
3.一个类仅有一个析构函数,若未显示定义,系统自动生成缺省构造函数。
4.当对象的生命周期结束时系统自动调用。
5.仅作清理工作(回收空间,关闭文件等),而不是删除对象。
拷贝构造函数
1.创建对象时用同类对象进行初始化。
2.参数必须使用引用传参(否则会造成无限递归)。
3.拷贝构造即构造函数的一个重载,是特殊的构造函数。
4.当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。这时要在内存建立一个局部变量,并把实参拷贝到新对象中去。
5.当函数的返回值值类的对象,函数执行完成返回调用者时使用。(先建立一个临时对象,再返回调用者)。
ps,局部变量在离开建立它的函数时就凋亡了,不可能在返回调用函数后继续生存,故编译器会在调用函数的表达式中创建一个无名临时变量,该临时对象的生存周期只在函数调用处的表达式中。所谓return对象,实际上是调用拷贝构造函数吧该对象的值考入临时对象中。
赋值语句
详细解析见程序。
ps:引用返回时,虽然可以节省空间和时间,但引用返回时要注意引用的对象,看引用的对象受不受函数作用域影响,若一出函数作用域就被析构,则不能引用返回。
class Test { public: //构造函数 Test(int data=0) :_data(data) {} //拷贝构造函数 Test(const Test &t)//形参一定要引用 { _data = t._data; } //赋值语句 Test& operator=(const Test&t) //Test& operator=(Test*const this,const Test&t),this表示当前对象地址 //引用传参,不用调用拷贝构造函数,不用再创建新空间存储临时对象,时间和空间均节省 //const表示是常引用,保护原对象不在函数内部被改变 //返回对象引用类型而不是void则在调用时可以出现连等赋值,且引用可以免去调用拷贝构造函数,时间和空间均节省 { if (this != &t)//判断自赋值,自己对自己赋值,无意义,浪费时间 { _data = t._data;//成员一一对应 } return *this; } /* void operator=(Test t) { if (this != &t) { _data = t._data; } } 若赋值语句这样写,则先调用拷贝构造函数(函数的形参是类的对象),再调用赋值语句,效率低,浪费空间 */ //析构函数 ~Test() { } private: int _data; }; int main() { Test t;//构造函数,构造函数 Test t1(10);//初始化,构造函数 Test t2 = t1;//初始化,对象构造对象,调用拷贝构造函数 Test t3; //Test t3();错误,这是一个函数声明,参数为空,不再是对象 t3 = t1;//t3.operator=(&t3,t1),直接调用赋值语句 //int value; //value = t4;//错误 }