虚函数
- 通过基类的指针删除派生类对象时,通常只调用基类的析构函数
- 但是删除一个攀升类对象时,应该先调用派生类的析构函数,然后调用基类的
- 解决办法:把基类的析构函数声明为virtual
- 派生类的析构函数可以virtual不进行声明
- 通过基类指针删除派生类对象时,首先调用派生类的析构函数,然后调用基类的析构函数
- 一般来说,一个类如果定义了虚函数,则应该将析构函数也定义成虚函数。或者,一个类打算作为基类使用,也应该将析构函数定义成虚函数
NOTICE:不允许将构造函数声明为虚函数
class son {public:~son() {cout << "bye feo son" << endl;}};class grandson:public:son {public:~grandson() {cout << "bye from grandson" << endl;}};main() {son * pson;pson = new grandson();delete pson;} // 输出 bye from son 没有执行 grandson::~grandson()!!!
纯虚函数和抽象类
纯虚函数:没有函数体的虚函数
class A {private: int a;public:virtual void Print() = 0; // 纯虚函数void fun() { cout << "fun"; }};
包含纯虚函数的类叫做抽象类
- 抽象类只能作为基类来派生新类使用,不能创建抽象类的对象
- 抽象类的指针和引用可以指向抽象类派生出的类的对象
A a; // wrong A是抽象类,不能创建对象
A * pa; // ok 可以定义指针和引用
pa = new A; // wrong 不能创建对象
- 抽象类的成员函数内可以调用纯虚函数,但是在构造函数或析构函数内部不能调用纯虚函数
- 如果一个类从抽象类派生而来,那么当且仅当它实现了基类所有纯虚函数,它才能成为非抽象类
class A {public:virtual void f() = 0; // 纯虚函数void g() { this->f(); } // ok 多态,一定是派生类的f()A() { f(); // 错 不是多态,函数体都没有 }};class B:public A {public:void f() { cout << "B:f()" << endl; }};main() {B b;b.g(); // 输出B:f()}
