c++ - 抽象基类中的析构函数保护在C++中不被继承?

标签 c++ inheritance visibility destructor compiler-generated

我发现我的代码中存在内存泄漏,这是由于仅调用对象的基类析构函数引起的。理解这个问题:我已经将 virtual 添加到接口(interface)类 MyÌnterface 的析构函数中。令我困惑的是,编译器显然为最终调用的辅助类 MyHelper 创建了一个标准析构函数。我用两个不同的编译器试过了。

这让我感到非常惊讶,因为我观察到如果成员或基类引入限制,则不会创建大多数默认实现。 为什么析构函数的保护没有被继承?

#include <iostream>

class MyInterface
{
public:
    virtual void doSomethingUseful()=0;
    // a lot more functions declared omitted
    virtual void doSomethingElse()=0;
    virtual void doSomethingIndividual()=0;
protected:
    /// protected destructor to forbid calling it on interfaces
    ~MyInterface() {} // HERE the virtual is clearly missing
};

/// a common base that defaults most functions implementations
class MyHelper: public MyInterface
{
public:
    void doSomethingUseful() {}
    // a lot more default implementations omitted
    void doSomethingElse() {}
};

class SomeImplementation: public MyHelper
{
public:
    SomeImplementation()
    {
        std::cout << "SomeImplementation ctr" << std::endl;
    }
    ~SomeImplementation()
    {
        std::cout << "SomeImplementation dtr" << std::endl;
    }
    void doSomethingIndividual()
    {
        std::cout << "SomeImplementation did it." << std::endl;
    }
};

/// user of MyInterface cannot delete object mi passed as parameter
int deleteSafeUsage(MyInterface& mi)
{
    mi.doSomethingIndividual();
    // would cause a compiler error: delete &mi;
}

/// usage restricted to MyHelper level, only exception is object creation
int testIt()
{
    MyHelper* h = new SomeImplementation;
    deleteSafeUsage(*h);
    delete h; // <- HERE the memory leak happens!
}

这里是上面示例代码的输出,它“显示”了缺少的 SomeImplementation ctr:

SomeImplementation ctr
SomeImplementation did it.

最佳答案

Constructors and destructors are not inherited .那么为什么他们的知名度会被继承呢?

您可能想要检查标准以确定,但是cppreference这么说,强调我的:

If no user-defined destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.

所以,如果你想让~MyHelper受到保护,你必须显式地声明它。

请注意,如果 MyInterface 有一个虚拟析构函数,则 MyHelper 的隐式析构函数也将是虚拟的。所以这方面是继承的,有点。同样,如果您想确定,您将需要引用标准,但这在 c++ faq lite 中有所提及。

为了完整起见,这里是 Herb Sutters关于如何在一般情况下和析构函数中使用虚拟的指南。

关于c++ - 抽象基类中的析构函数保护在C++中不被继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21985200/

相关文章:

c++ - gmock : check only one element of vector

c++ - 如何使用 winapi 向某些网站发送 POST 请求?

scala - 以下 'illegal inheritance' (Scala 2.9.2) 背后的原因是什么?

c# - 如何将虚拟属性添加到密封类

c# - 当宽度变小时,VisualStateManager 不会在 UWP 中隐藏控件

wpf - 调整 View 的可见性属性不起作用

c++ - 如何检测 W2A 转换是否完全成功

c++ - 如何初始化值为结构的类的私有(private)成员静态映射?

ruby - 将值传递给 Ruby 类

.net - 在WPF中,如何确定控件是否对用户可见?