在C++里,如果程序者不指定,编译器会自动生成一些函数,而且是,只有在这些函数被需要时才会被编译器创建出来,比如:
A a; //default constructor 和 default destructor
A b(a); //default copy constructor
b = a; //default copy assignment
所以编译器也不会默认就把这些默认都创建出来的。
POINT 10,如何阻止编译器的默认产生的函数:构造,析构,复制构造,复制赋值
关于构造和析构就不说了,只要自己显示定义,那编译器就不会自己生成了。这里只讲一下copy constructor和copy assignment,该如何既阻止编译器自己产生,又阻止被调用的方法,其实做法很简单,就和Singleton的实现方法一样,如下:
class A
{
public:
A(){};
~A(){};
private:
A(const A& a); //将copy constructor声明为private,并且不加以实现
A& operator = (const A& a); //将copy assignment声明为private,并且不加以实现
}
这样做带来的好处为:
1. 如果基类将copy constructor和copy assignment声明为private,那么编译器将拒绝为其derived class自动生成copy constructor和copy assignment.
2. private的另一个目的是阻止被其他类调用。但不能阻止该类的friend类和子类使用。
3. 针对如果该类的friend类或derived class想用父类的copy constructor或assignment,因为这里没有该声明的实现,编译器虽然发现不了,但是链接器却能知道,估计就是LNKError2019等,找不到对应的实体,同样能阻止被调用。
POINT 10,virtual 析构函数
编译器为我们自动生成的析构函数可不是virtual的,这个要很注意,否则,如果你的类里支持多态的函数,肯定会有问题,什么问题大家也应该知道,就是子类对象不会被销毁,只能把父类对象销毁。
virtual类型的析构函数遵循下面的规则,因为并不是非要声明为virtual才行,这个virtual必定还是会占用部分内存来存储它的virtual table的。
1. 带多态(polymorphic)性质的基类需要声明一个virtual 析构函数。
2. 如果该class有替他virtual类型的函数,则需要声明一个virtual的析构函数。
另外对于不需要声明的情况如下:
如果该class的目的不是作为基类使用,或是不带有多态性质的函数,则不需要声明virtual析构,比如STL库,所以,我们一定不要继承STL的类,否则会出问题的,因为STL的析构是不会调用你继承类的析构的。
另外一点,我以前一直都有错误理解的就是,我认为如果父类的析构为virtual的,那么在子类的析构也一定要显示的声明为virtual的,但实际上是没有必要的,如果我们不需要显示的声明子类的析构,我们的子类还是会被销毁的,因为父类声明成virtual就足够了。