我正在用虚拟析构函数做一个小实验来回顾一下--想知道是否有人对以下问题有一个简单的解释(使用VS2010):
我定义了类层次结构A-B-C-D,D继承C,C继承B,B继承A,A是基础;
运行了2个实验:
第一个实验-
A有一个虚拟析构函数。
B具有非虚拟析构函数
C有一个虚拟析构函数
%d具有非虚拟析构函数
//
在D类型的堆上分配4个对象-在第一个3处指向A*,B*和C*的指针-为了完整性,将第4个对象保留为D*。删除所有4个指针。
正如我所料,在所有4个实例中,完整的析构函数链都是以从D到A的逆序执行的,从而释放所有内存。
第二个实验-
A具有非虚拟析构函数**将A更改为非虚拟
B具有非虚拟析构函数
C有一个虚拟析构函数
%d有一个非虚的Distructor
在类型为D的堆上分配4个对象-在第一个3处指向A*、B*和C*的指针-为了完整性,将第4个对象保留为D*。
删除C*和D*指针:整个析构函数链以从D到A的逆序执行,释放所有内存。
删除B*:B,然后运行析构函数(泄漏)
删除A*:仅运行析构函数(泄漏)
有人能解释一下为什么会这样吗?
当在实验2中分配D类型对象时,它的直接基类(C)有一个虚拟析构函数-这不是告诉编译器用Vptr跟踪它并知道内存类型吗?不管引用是什么?
谢谢,迈克
发布于 2012-06-16 00:58:30
当在实验2中分配D型对象时,它的直接基类(C)有一个虚拟析构函数-这不是告诉编译器用Vptr跟踪它并知道内存类型吗?不管引用是什么?
不是的。
在第二个测试用例中,A和B没有vptrs/vtable。(即使它们这样做了,非虚拟成员函数仍然是静态解析的,而不是动态解析的。)
换句话说,基类不会从派生类“继承”信息(比如函数是否为虚函数)。
发布于 2012-06-16 01:01:21
当您删除没有虚拟析构函数的A*时,编译器在编译时不知道它将在运行时指向具有虚拟析构函数的对象。删除可能是具有虚拟析构函数的对象--也可能不是。不会发生动态绑定。
发布于 2012-06-16 01:00:06
你的实际问题是为什么要使用虚拟析构函数而不是非虚拟析构函数?因为拥有一个带有非虚拟析构函数的基类是不好的。请参阅the faq
https://stackoverflow.com/questions/11055089
复制相似问题