C++中的虚默认析构函数

25

我有一组大量的继承类(criteria),它们都继承自一个基类(criterion)。这是criterion的代码:

class criterion
{
public:
    virtual unsigned __int32 getPriorityClass() const = 0;
    virtual BOOL include(fileData &file) const = 0;
    virtual void reorderTree() = 0;
    virtual unsigned int directoryCheck(const std::wstring& directory) const = 0;
    virtual std::wstring debugTree() const = 0;
};

从这个类派生出来的一些例子:

class fastFilter : public criterion
{
public:
    void reorderTree() {};
    unsigned int  directoryCheck(const std::wstring& /*directory*/) const { return DIRECTORY_DONTCARE; };
    unsigned __int32 getPriorityClass() const { return PRIORITY_FAST_FILTER; };
};

class isArchive : public fastFilter
{
public:
    BOOL include(fileData &file) const
    {
        return file.getArchive();
    }
    std::wstring debugTree() const
    {
        return std::wstring(L"+ ISARCHIVE\n");
    };
};

由于我这里根本没有析构函数,但是这应该是一个基类,那么我需要插入一个空的虚拟析构函数吗?就像这样:

virtual void ~criterion() = 0;

如果需要虚拟析构函数声明,那么所有中间类都需要一个吗?也就是说,fastFilter 是否也需要一个虚拟析构函数?


以上不是一个空析构函数。它是一个同时也是纯虚函数的析构函数。这与是否为空无关,事实上析构函数很特殊,即使它是纯虚的,也必须始终有定义。 - Richard Corden
4个回答

53

是的 - 基类需要一个虚析构函数,即使它是空的。如果不这样做,那么当使用基类指针/引用delete派生对象时,派生对象的成员对象将无法得到适当的销毁机会。

派生类不需要声明或定义自己的析构函数,除非它们需要除默认析构函数行为之外的其他内容。


为什么不将其标记为默认值?而不是写成“= 0”,可以写成“= default”。 - Vlad

33

建议插入:

virtual ~criterion() {}

从C++11开始,你可以使用= default;代替空体{}

这是为了避免使用基类指针删除时出现问题。否则,由于派生类的析构函数不会被调用,你将泄漏内存。

criterion *c = new fastFilter();
delete c; // leaks

1
有没有使用空析构函数而不是纯虚拟析构函数的理由? - Billy ONeal
1
“virtual ~criterion() noexcept {}” 不是更漂亮吗? - user1095108
6
@user1095108,virtual ~criterion() = default 这样写更简洁明了吗? - user35443
1
@user35443:在2009年时,"=default"并不存在。这是C++11中新增的内容。是的,现在我认为这将是首选选项。 - Pacheco
@Pacheco 啊,看起来三年前我没有注意到答案已经在'09年写好了。天哪,时间过得真快... - user35443

13

您不需要把析构函数变成虚函数,只需要给它一个空实现即可:

virtual ~criterion() { }

这样你就不必在每个子类中都实现它,但仍然每个子类都会有一个(继承的)虚析构函数。


7
一点与其他人已经回答的不同:
不要使用

virtual void ~criterion() = 0;

所需版本为:
    virtual ~criterion() {}  //Note: Removed void as destructors not allowed 
                             //  a return type

了解更多关于虚析构函数的信息,请查看FAQ中的此链接:我的析构函数应该何时是虚拟的?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接