从非虚拟父级继承虚拟类的正确方法

时间:2012-01-07 11:19:22

标签: c++ inheritance virtual-destructor

我编写了这个使用三种类型的测试代码:struct One是没有虚拟成员的普通类型,struct Two : One有一个纯虚函数和一个虚析构函数,struct Three : Two实现Two的接口。

#include <iostream>

struct One
{
    ~One() {
        std::cout << "~One()\n";
    }
};

struct Two : One
{
    virtual ~Two() {
        std::cout << "~Two()\n";
    }

    virtual void test() = 0;
};

struct Three : Two
{
    virtual ~Three() {
        std::cout << "~Three()\n";
    }

    virtual void test() {
        std::cout << "Three::test()\n";
    }
};

int main()
{
    Two* two = new Three;
    two->test();

    One* one = two;
    delete one;
}

不出所料,the output was这个:

  

三个::测试()
  〜一()

除了让每个析构函数都虚拟之外,还有什么方法可以解决这个问题吗?或者程序员应该注意不要遇到这种情况?我觉得奇怪的是编译时没有任何警告。

4 个答案:

答案 0 :(得分:2)

唯一的“修复”不是通过指向One的指针删除对象。

如果这是一个经常出现的问题,取决于您的课程的使用方式。例如,标准库包含像unary_function这样没有虚拟析构函数的结构,但我们几乎没有看到它像这样被滥用。

答案 1 :(得分:2)

delete one调用未定义的行为,因为对象的动态类型与静态类型不匹配,静态类型没有虚拟析构函数。

避免这样的问题的通常方法是使析构函数成为公共和虚拟,或者是受保护的和非虚拟的(在预期以这种方式使用的类上)。

答案 2 :(得分:1)

你必须小心,让One的析构函数变为虚拟。有些编译器会对此发出警告。

答案 3 :(得分:1)

如果要在派生类中使用析构函数,则必须将它们定义为虚拟。这是唯一的方法。