为驳回编译器自动(暗自〉提供的机能,可将相应的成员函数声明为private 并且不予实现。使用像Uncopyable 这样的base class 也是一种做法。
例如,要阻止类的拷贝构造函数,不去申明,但是,编译器会自动帮你申明拷贝构造函数,如何阻止该构造函数的申明呢,方法是,将该构造函数,设置为私有类型的申明,但不做定义,此时,可以省略参数名称。
但这个方法不是绝对安全。因为成员函数和友元函数还是可以调用该拷贝构造函数。除非不去定义拷贝构造函数和成员函数。更好的方法是,将该链接期出现的错误(如果有人调用拷贝构造函数)推置编译期提示,会更好,实现的方法是,专门设计一个阻止拷贝的基类,然后,我们的实际类,私有继承于该基类。
一般来说,如果一个类要被另外一个类继承,而且用其指针指向其子类对象时,如题目中的A* d = new B();(假定A是基类,B是从A继承而来的派生类),那么其(A类)析构函数必须是虚的,否则在delete d时,B类的析构函数将不会被调用,因而会产生内存泄漏和异常; 在构造一个类的对象时,先构造其基类子对象,即调用其基类的构造函数,然后调用本类的构造函数;销毁对象时,先调用本类的析构函数,然后再调用其基类的构造函数;
任何class 只要带有virtual 函数都几乎确定应该也有一个virtual析构函数。如果class 不含virtual 函数,通常表示它并不意图被用做一个base class。当class不企图被当作base class,令其析构函数为virtual 往往是个馒主意.因为根据虚函数的C++实现机制,对象的体积会增加。许多人的心得是:只有当class 内含至少一个virtual 函数,才为它声明virtual 析构函数。
同时,也可以用纯虚函数实现这个功能,但是,这种情况下的纯虚函数,必须要有定义。
析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class 应该提供一个普通函数(而非在析构函数中)执行该操作。
绝不在构造和析构过程中调用virtual 函数。
假设有基类A已经派生出来的类B,现在B b表示定义一个类B的对象,然而,构造b时,编译器首先调用基类的构造函数A,假如构造函数A中调用了虚函数,那么,尽管b对象是类B的,但,此时类A中的构造函数调用的虚函数,还是将对象b看做是类A对象,无视其本身属性。也就是说,在这个构造期间,虚函数,不会下降到派生类,即,在此期间,虚函数,不是虚函数。同样,析构函数也是这样。
由于在此期间,无法使用虚函数从基类下降到派生类,则可以借由派生类将必要的信息上传给基类。所以,派生类的构造函数采用初始化列表,来传递,因为初始化列表的运行在构造函数之前。
但是,比起初始化列表给基类必要信息,用一个辅助函数创建一个值传递给构造函数更方便。并设定其为静态的。