代码之家  ›  专栏  ›  技术社区  ›  uuu777

具有非虚拟目标机的双重继承(Y形)

  •  0
  • uuu777  · 技术社区  · 7 年前

    我有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”的.c c文件中是否应存在到d的定义?

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

    3 回复  |  直到 7 年前
        1
  •  2
  •   Phil1970    7 年前

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

    因此因为 C 析构函数是虚拟的,您可以通过指向 C , D 将调用析构函数。

    如果既不 A 或 B 析构函数将是虚拟的,那么删除 D 对象,但这里不是这样。

    如果一个类 C 从类派生,然后它知道如何销毁其基类。因此 乙 始终调用析构函数(假定您从最终对象或析构函数显式或隐式为虚拟的级别中删除该对象)。

    实际上,即使在未定义的情况下(仅 D 析构函数是虚拟的,对象通过 C 指针) 乙 可能会调用析构函数,但是 D 部分不会被正确销毁。 但是,因为它是未定义的,你不能依赖它 .

        2
  •  1
  •   eerorika    7 年前

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

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

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

    我怀疑有些角落的案例中~b()没有被执行-有可能吗?

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

        3
  •  0
  •   Adrian Shum    7 年前

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

    当您通过基类指针删除一个派生类实例时,描述器的虚拟特性就会显现出来。

    在上面的示例中,假设 ~C 不是虚拟的(即您没有为任何析构函数声明虚拟的),如果您正在删除 D 实例通过 C* ,d的desctructor可能已丢失,编译器将调用 ~C 而是为了你。如上所述,致电 ~C 将导致所有的基类去流通器( ~A 和; ~B )自动调用。

    但是,假设您已经在基类中将析构函数声明为虚拟的( A 等等),虚拟性将传播到所有派生类的析构函数。也就是说,即使你还没有宣布 ~C 作为虚拟的,它实际上是虚拟的。