3

我在我的代码中发现了一个内存泄漏,这是由于仅调用对象的基类析构函数引起的。这个问题理解:我已经virtual在接口类的析构函数中添加了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.
4

1 回答 1

5

构造函数和析构函数不是继承的。那么为什么他们的知名度会被继承呢?

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

如果没有为类类型(结构、类或联合)提供用户定义的析构函数,编译器将始终将析构函数声明为其类的内联公共成员。

所以,如果你想~MyHelper受到保护,你必须明确声明它。

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

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

于 2014-02-24T10:53:30.020 回答