1、首先需要了解父类和子类的内存分布
如下图,B类(子)继承A类(父):
2、其次就是delete删除对象原理
delete就是依据指针指向的内存地址,如何删除内存数据,具体删除多少呢?那就看指针类型了。
如果指针类型为A*,那就删除A类大小的内存。
3、按1、和2中的内容,那么冒出一个问题!
看如下代码:
A* a = new B();//按上图方式,B继承于A,此处为隐性转换,向上类型转换delete a;
父类指针指向子类对象的情况会怎么删除?
依据上面内容推测,B类中的A对象段的内存将会被删除,而剩余的B自己的数据将不会,这样不是造成内存泄漏了!!!貌似好像是这样。
说明:上面的图片仅用于理解,其实B类不分配堆空间(使用new),是不会造成内存泄漏的。
这里为什么我们可以认为delete一个基类指针(基类是没有析构函数),不会照成内存泄漏呢?这就是C++的new 和 delete 的特有机制和职责了.下面看这句话:
“…当在堆栈里主动创建对象时,对象的大小和它们的声明周期被准确地内置在生成的代码里,这是因为编译器知道确切的类型,数量和范围…”(摘自: C++编程思想 2卷合订本 第318页的)这里非常明确的告诉我们,会知道确切的"类型,数量和范围",注意这里有"范围",因此可以推断通过基类指针进行delete,是不会对“不会对程序有直接影响”(备注:请谅解,我没敢直接说不会有内存泄漏,因为我没有能跟编译器厂商求证,但我认为是"应该"不会造成内存泄漏).
4、针对这个问题有什么解决方法?
将父类析构函数设置为虚函数,也就是函数前面加“virtual”即可解决此问题。
这样的情况下,delete a会先执行子类的析构函数后,再执行父类的析构函数。
(1) 父类析构函数不虚化,运行情况如下:
A();B();~A();
(2) 父类析构函数设为虚函数,运行情况如下:
A();B();~B();//!!! 不同点 !!!~A();