具有非虚拟destirutor的双重继承(Y形)

Double inheritance with non-virtual destirutor (Y-shaped)

本文关键字:继承 虚拟 destirutor      更新时间:2023-10-16

我有Y形的类层次结构:类C继承自A和B,类D继承自C。A和B有虚拟析构函数,而C的析构函数不是虚拟的。我知道如果没有双重继承(说没有B)~C()将是虚拟的。我的问题是双重继承会影响它吗?

class A { virtual ~A(); ...};
class B { virtual ~B(); ...};
class C : public A, public B { ~C(); ...};
class D : public C { virtual ~D(); ... };

我必须通过指向C.的指针删除类D的实例

C* c = new D;
delete c;

我怀疑有些情况下~B()没有被执行——这可能吗?它是否取决于优化级别?在调用"delete c"的.cc文件中是否应该存在to D的定义?

除了~B()之外的所有析构函数都是nops,类C是空类:没有数据成员,没有函数,只有一个平凡的构造函数和一个空析构函数。我在所有情况下都写了几个测试程序~B()被执行,但我确信我没有尝试所有可能的组合。

C析构函数是隐式虚拟的,因为它的基析构函数中至少有一个是虚拟的。

因此,因为C析构函数是虚拟的,并且您通过指向C的指针进行删除,所以会调用D析构函数。

如果AB析构函数都不是虚拟的,那么删除D对象将是未定义的行为,但这里的情况并非如此。

如果类C派生自类,那么它知道如何销毁其基类。因此,B析构函数将始终被调用(假设您删除了最终对象,或者从析构函数是显式或隐式虚拟的级别中删除

在实践中,即使在未定义的情况下(只有D析构函数是虚拟的,对象是通过C指针删除的),也可能会调用B析构函数,但D部分不会被正确销毁但由于它是未定义的,您不能依赖它

C的析构函数不是虚拟的。

是的。它有一个带虚拟析构函数的基,所以C的析构函数是隐式虚拟的。析构函数是否显式声明为虚拟是无关紧要的。D.的析构函数也是如此

我必须通过指向C的指针删除类D的实例。

我怀疑有些情况下~B()没有被执行——这可能吗?

只要C的析构函数是虚拟的,就没有问题。如果C的析构函数不是虚拟的,那么通过指向C的指针删除一个dervied对象将具有未定义的行为。

据我所知,析构函数链接与虚拟析构函数无关。只要调用了某个类的析构函数,它就会自动为您调用基类解构函数。

当您通过基类的指针删除派生类实例时,Desconstructor的虚拟性就会显现出来。

在上面的例子中,假设~C不是虚拟的(即,您没有为任何析构函数声明虚拟的),并且如果您通过C*删除D实例,则可能会错过D的析构函数,编译器将为您调用~C。如上所述,调用~C将导致所有基类去分配器(~A&~B)被自动调用。

然而,假设您已经在基类(A等)中将析构函数声明为虚拟的,那么虚拟性将传播到所有派生类的析构函数。这意味着,即使您没有将~C声明为虚拟的,它实际上也是虚拟的。