【问题标题】:Correct way to inherit from a virtual class with non-virtual parent从具有非虚拟父级的虚拟类继承的正确方法
【发布时间】:2012-02-04 20:33:49
【问题描述】:

我编写了这个使用三种类型的测试代码: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 这个:

三::test()
〜一个()

除了将每个析构函数设为虚拟之外,还有其他方法可以解决此问题吗?还是程序员应该小心不要遇到这种情况?我觉得编译时没有警告很奇怪。

【问题讨论】:

  • 一个简单的解决方法:使用来自 One 的私有或受保护继承,并通过使用声明公开功能。

标签: c++ inheritance virtual-destructor


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    这是否是常见问题取决于您的类的使用方式。例如,标准库包含像 unary_function 这样没有虚拟析构函数的结构,但我们很少看到它被这样滥用。

    【讨论】:

    • 为了强制执行,One 的析构函数应该受到保护
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-02-04
        • 2016-03-04
        • 2016-10-26
        • 2015-09-09
        • 1970-01-01
        • 2016-05-20
        • 1970-01-01
        • 1970-01-01
        • 2012-09-27
        相关资源
        最近更新 更多