说明以下程序的显示结果:
#include <iostream> using namespace std; class A { public: A() {cout<<"This is A()"<<endl;} ~A() {cout<<"This is ~A()"<<endl;} virtual void hello() { cout<<"Hello A"<<endl; } }; class B:public A { public: B() {cout<<"This is B()"<<endl;} ~B() {cout<<"this is ~B()"<<endl;} void hello() { cout<<"Hello B"<< endl; } }; int main() { A *ptr = (A *)new B(); //B *ptr = new B(); ptr->hello(); delete ptr; return 0; }
显示结果:
This is A() This is B() Hello B This is ~A()
即没有调用B的析构函数
解析:
一般情况下构造函数调用父类-》子类;析构函数调用子类-》父类
比如这么写
B *ptr=new B(); 先 析构 B类 再析构A类
但如果是上面那种写法
A *ptr=(A *)new B(); ... delete ptr;
结果就是构造函数相同,析构函数只调用A,因为ptr的类型是A,delete ptr时将调用类型A的析构函数;没析构B,造成内存泄露
一般遇到这样的现象,需要将基类的析构函数定义为虚拟的
这样的话,情况就是:析构函数调用过程为子类->父类,不过内部原理不一样 delete ptr时调用类型A的析构函数步骤如下:
1,到虚函数映射表中查找A的实际析构函数;
2,发现被实例化为B的析构函数;
3,调用B的析构函数;
4,调用A的析构函数--如果A的析构不是纯虚函数的话
运行结果为:
This is A() This is B() Hello B this is ~B() This is ~A()
即调用了B的析构函数
另这里基类的hello()函数是虚函数,所以ptr->hello()用的是子类的hello()函数,如果基类的hello()不是虚函数,则会调用基类的hello()