先看第一种情况父类和子类都没有virtual,使用父类的指针创建对象,并用父类指针删除对象
#includeusing namespace std; //基类Base1 class Base1 { public: Base1() { cout << "Base1构造函数" << endl; } ~Base1() { cout << "~Base1析构函数" << endl; } }; //派生类Base2 class Base2 : public Base1 { public: Base2() { cout << "Base2构造函数" << endl; } ~Base2() { cout << "~Base2析构函数" << endl; } }; int main() { //基类指针指向用new运算符动态生成的派生类对象 Base1 *base1=new Base2; delete base1; return 0; }
输出结果如下:很遗憾~Base2析构函数并没有执行,这会导致Base2中的成员内存泄漏
Base1构造函数 Base2构造函数 ~Base1析构函数情况二
第二种情况,我们使用子类指针创建对象,同时删除子类指针的对象;
即 Base2 *base2=new Base2; delete base2;
#includeusing namespace std; //基类Base1 class Base1 { public: Base1() { cout << "Base1构造函数" << endl; } ~Base1() { cout << "~Base1析构函数" << endl; } }; //派生类Base2 class Base2 : public Base1 { public: Base2() { cout << "Base2构造函数" << endl; } ~Base2() { cout << "~Base2析构函数" << endl; } }; int main() { //基类指针指向用new运算符动态生成的派生类对象 Base2 *base2=new Base2; delete base2; return 0; }
输出结果如下:输出结果是正常,父类和子类析构函数都执行了
Base1构造函数 Base2构造函数 ~Base2析构函数 ~Base1析构函数3 情况三
我们使用虚函数Base1, 然后使用子类创建对象和删除对象
Base1 *base1=new Base2; delete base1;
#includeusing namespace std; //基类Base1 class Base1 { public: Base1() { cout << "Base1构造函数" << endl; } virtual ~Base1() { cout << "~Base1析构函数" << endl; } }; //派生类Base2 class Base2 : public Base1 { public: Base2() { cout << "Base2构造函数" << endl; } ~Base2() { cout << "~Base2析构函数" << endl; } }; int main() { //基类指针指向用new运算符动态生成的派生类对象 Base1 *base1=new Base2; delete base1; return 0; }
输出结果:正常输出结果,2个析构函数都调用了
Base1构造函数 Base2构造函数 ~Base2析构函数 ~Base1析构函数
总结:
1.只要基类的析构函数是虚函数,那么派生类的析构函数不论是否用virtual关键字声明,都自动成为虚析构函数,即使派生类的析构函数与基类的析构函数名字不相同。
2. 在设计框架的时候都喜欢抽象,所以建议父类的析构函数都设置成虚函数,避免子类内存泄漏
3. 析构函数的虚函数和普通虚函数表不同,普通函数的虚函数是子类替换父类的函数指针,但是析构函数不是替换关系



