条款5:定义好一个空类时,编译器会自动生成无参构造函数、copy构造函数、copy assignment(拷贝赋值)操作符和析构函数
程序员自定义的函数的优先级高于编译器自动生成的,当程序员自己实现了上述函数时,编译器就不会生成默认的函数。但是,当编译器生成的默认函数无法满足你的功能时,就需要程序员自己去定义函数了。
条款6:当不想使用编译器生成的默认函数时,将这些不想使用的默认函数自己声明为private,并且只声明,不实现
如果仅仅声明为private的,且实现了(即使是空实现),类的friend函数和成员函数还是可以正常调用这些默认函数,所以为了不被正常调用,我们仅仅声明,而不做实现。
条款7:作为多态和基类使用的类应该将析构函数声明为virtual析构函数
作为基类的类的析构函数应该声明为virtual虚析构函数。
借用一个典型的类为例:
class Base {
public:
~Base() {
cout << "~Base()" << endl;
}
};
class Derived1 : public Base {
public:
Derived1():name_(new string("NULL")) {}
Derived1(const string& n):name_(new string(n)) {}
~Derived1() {
delete name_;
cout << "~Derived1(): name_ has been deleted." << endl;
}
private:
string* name_;
};
class Derived2 : public Base {
public:
Derived2():name_(new string("NULL")) {}
Derived2(const string& n):name_(new string(n)) {}
~Derived2() {
delete name_;
cout << "~Derived2(): name_ has been deleted." << endl;
}
private:
string* name_;
};
int main() {
Base* base[2] = {
new Derived1(),
new Derived2("Bob")
};
for (int i = 0; i != 2; ++i) {
delete base[i];
}
return 0;
}
上述代码运行的结果就是只调用了基类的析构函数,而未调用派生类的析构函数。原因就是采用的静态绑定,指针的类型就是基类类型,自然就只调用了基类的析构函数。要想改变现状,需要将基类的析构函数声明为virtual的,使其变成动态绑定,指针在运行时期是什么类型就会调用对应类型的析构函数。
多态的意思是基类的函数定义为virtual函数,在子类中重写此函数。运行时会根据实际的类型选择要调用的是基类函数还是子类函数。具体事例可以参考: