C ++类接口类的析构函数

时间:2010-04-22 14:19:22

标签: c++

开始在现有代码库上使用PC-Lint(恐惧和恐惧)。

它抱怨的一件事是:

 class IBatch
 {
 public:
    virtual void StartBatch() =0;
    virtual int CommitBatch() =0;
 };

当另一个类派生于此时,将其用作接口

base class 'IBatch' has no destructor

所以,问题是:当您创建如上所述的 Interface 类时,您是否始终包含虚拟析构函数?为什么? (是样式还是编码错误?)

编辑:应该说我不希望或希望IBatch的用户破坏,他们只是一个服务的消费者,通过这个接口到一些外部实现类(如果那样的话)有所作为)

6 个答案:

答案 0 :(得分:28)

  

基类析构函数应该是public和virtual,或者是protected和nonvirtual。

(Herb Sutter, Guru of the Week #18: "Virtuality")

答案 1 :(得分:8)

编码错误 - 如果通过指向基类的指针调用,派生类的析构函数将永远不会被调用。

实现IBatch并通过指向基类的指针(指向IBatch的指针)引用派生类,并在指向基类的指针上调用delete最终导致内存泄漏,因为派生类的析构函数永远不会被调用。

基本规则是当一个类至少有一个virtual方法需要virtual析构函数时。

class IBatch
{
    public:
       virtual void f() = 0;
};

class A : public IBatch
{
    public:
       void f() {}
       ~A() {}
};

IBatch * a = new A();
a->f();    // calls A::f()
delete a;  // calls IBatch::~IBatch() not A::~A()

答案 2 :(得分:7)

如果有虚函数,则需要有一个虚析构函数。总是。它只是一个接口类并不重要 - 它仍然需要虚拟析构函数。

要么是,要么需要protected非虚拟析构函数。但是你不能使用界面指针删除对象。

答案 3 :(得分:4)

具有虚函数但没有虚拟析构函数的类是可疑的,并且很可能是错误的:查看更好更准确的解释here

答案 4 :(得分:2)

  

所以,问题是:何时创建   像上面这样的接口类,做   你总是包括一个虚拟的   析构函数?为什么? (是风格还是风格   编码错误?)

这真的取决于它。如果您曾在IBatch指针上调用delete,那么它可能无法满足您的期望。当然,如果您有虚拟Init / Shutdown或AddRef / Releases之类的东西,那么它并不是真正的问题。

答案 5 :(得分:0)

编译器放置非虚拟的默认析构函数,这意味着指向虚拟基类的指针上的“删除”将成功导致内存泄漏。因此,它是一个实现缺陷,无论是样式还是编码错误。