//条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构。 // 2.如果一个类不含有虚析构函数,那么通常表示它并不希望其本身成为一个基类。 // 3.不要为普通的类声明一个虚析构函数。这是因为C++为了实现虚函数,会建立一个由函数指针构成的数组,称为虚函数表,导致类的对象必须携带额外信息来决定运行期间哪个虚函数会被调用,这个额外信息通常由一个指针组成,此指针指向虚函数表。 // 4.由3可知,当为类声明一个虚析构函数的时候,会使得类的对象占用更多的内存,在32位程序下,会多出4字节,在64位程序下会多出8字节. class CTest { public: virtual ~CTest(){} public: int value0; int value1; }; int size = sizeof CTest; //size = 16 64位程序,若去掉虚析构函数,则size = 8; // 5.当一个类不包含虚析构函数的时候(比如string),不要在此类的基础上进行派生,否则在删除对象的时候可能会导致异常。原因见1。 //条款09:绝对不要在构造和析构过程中调用虚函数 // 1.如下代码,当构造CChild类的成员的时候,其父类的成员首先被构造,则先调用其父类的构造函数,其父类构造函数中调用了一个虚函数,此时并不会发生动态绑定,这里调用的虚函数是父类的版本。对象析构的时候也是如此。 class CFather { public: CFather() {fun();} virtual void fun(){printf("Father virtual ");} }; class CChild : public CFather { public: CChild() {fun();} virtual void fun(){printf("Child virtual ");} }; CChild child; //输出Father virtual Child virtual 而不是 Child virtual Child virtual //条款12:复制对象时勿忘其每一个成分 // 1.复制所有本类的成员变量,调用其基类的适当的拷贝函数 // 2.通常拷贝构造函数与拷贝赋值运算符所做的工作很接近,但是最好不要让其中一个调用另一个,应该定义一个新的函数,供这两个函数调用。 // 3.令拷贝赋值运算符调用拷贝构造函数是不合理的,因为这就像试图构造一个已经存在的对象,这是很荒谬的。 // 4.令拷贝构造函数调用拷贝赋值运算符也是不合理的,因为拷贝构造函数是用来初始化新对象,而拷贝赋值运算符只实施在已初始化的对象上,所以从逻辑上讲也是不合理的。