A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 wuqiong 于 2018-6-28 09:34 编辑

条款5:编译器可以暗自为class创建default构造函数、copy构造函数、copy assignment操作符,以及析构函数。


不过,仅仅是需要的时候,编译器才自动生成。如遇到下面代码时

NameClass A;    //defalut构造函数、析构函数

NameClass B(A); //copy构造函数

编译器才生成对应构造函数和析构函数。


编译器生成的构造函数,会为base classes和non-static成员变量赋值。


编译器为某个类生成copy构造函数和copy assignment操作符,需要满足两个条件:生成的代码合法,有适当机会证明它有意义。


例如,当某个类里面有const的non-static成员函数的时候,编译器讲拒绝生成构造函数,即拒绝编译那一行。这个时候就必须自己定义copy构造函数。

试了下,在VC6里,在成员初始化列表里初始化非静态的const成员变量后,编译器就可以自动生成copy构造函数了。未初始化时,则不能。


还有一种情况,当class中有引用类型的成员变量时,编译器也不能自动生成copy构造函数。


如果某个base classes所生成的copy assignment操作符声明为private,编译器也就无法为derived classes自动生成了。


条款6:为驳回编译器自动提供的技能,可将相应的拷贝构造函数等等声明为private并且不予实现。但,友元函数和成员函数还是可以使用private的拷贝构造函数的。更进一步的,使用一个有private的拷贝构造函数的base classes,可以微妙的阻止编译器自动生成drived classes的拷贝构造函数。


条款7:带有多态性质的base classes应该有一个virtual析构函数。如果class带有任何virtual函数,也就应该拥有一个virtual析构函数。


请记住:class的设计目的,如果不是作为base classes使用,或不是为了具备多态性,就不该声明virtual析构函数。


当你不希望某个类被实体化时,可以为其声明一个pure virtual函数。如果没有pure virtual函数,可以声明一个pure virtual析构函数。同时,又必须定义该pure virtual析构函数,因为析构函数是派生类无法重新定义的,而多态性又需要。


条款8:析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能跑出异常,析构函数应该能捕捉任何异常,然后吞下它们或结束程序。

如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数执行该操作,而非在析构函数中。总之,析构函数不可以抛出异常。


条款9:在构造和析构期间,不要调用virtual函数,因为这类调用从不下降至derived class。就是说,在base class的构造函数运行时,其中的virtual函数无法只能调用base自己的,因为derived的virtual函数还是未定义状态。

解决方法是:采用static函数,从derived class构造函数向base class构造函数传递信息。


条款10:令operator= 返回一个reference yo *this,即返回赋值操作符左边参数的引用。这是为了连锁赋值,就像

a = b = c = d = 0;


条款11:在operator= 中处理“自我赋值”的问题,做到证同,和异常安全。

确保当对象自我赋值时,operator=有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap。

确定任何函数,如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。


条款12:拷贝构造函数和拷贝赋值操作符,应该确保复制对象内所有的成员变量,和base class成分。

另外,不要在拷贝构造函数中调用拷贝复制操作符operator=,反之亦然。应该讲他们共同的技能放进第三个函数中,并由2个copy函数共同调用。Because,拷贝构造函数的作用是函数初始化,而operator=的作用是对已初始化过的类进行赋值。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马