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

Posted

技术标签:

【中文标题】C++ 中的虚拟默认析构函数【英文标题】:Virtual Default Destructors in C++ 【发布时间】:2010-10-24 01:18:27 【问题描述】:

我有大量继承自基类(标准)的继承类(标准)。这是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;

如果需要虚拟析构函数声明,是否所有中间类也都需要一个? IE。上面的 fastFilter 是否也需要一个虚拟析构函数?

【问题讨论】:

上面不是空的析构函数。它是一个析构函数,也是一个纯虚函数。这与为空无关,事实上析构函数的特殊之处在于它必须始终有一个定义,即使它是纯虚拟的。 【参考方案1】:

是的 - 基类需要一个虚拟析构函数,即使它是空的。如果不这样做,那么当 delete 通过基指针/引用作为派生对象时,派生对象的成员对象将没有机会正确地销毁自己。

派生类不需要声明或定义自己的析构函数,除非它们需要默认析构函数行为以外的东西。

【讨论】:

为什么不将其标记为默认值?而不是“= 0”放下“=默认”【参考方案2】:

建议插入:

virtual ~criterion() 

从 C++11 开始,您可以使用 = default; 代替空主体

这是为了避免从基类的指针中删除问题。否则你会泄漏内存,因为派生类的析构函数不会被调用。

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

【讨论】:

有什么理由使用空析构函数而不是纯虚拟析构函数? virtual ~criterion() noexcept 不是更漂亮吗? @user1095108,virtual ~criterion() = default 不是更漂亮吗? @user35443:“=default”在 2009 年不存在。它是在 C++11 中添加的。是的,现在我认为这将是首选。 @Pacheco 啊,看来三年前我没有注意到答案是在 09 年写的。哎呀,时间过得真快……【参考方案3】:

你不需要把析构函数抽象化,给它一个空实现即可:

virtual ~criterion()  

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

【讨论】:

【参考方案4】:

与其他人已经回答的一个小变化:

代替

virtual void ~criterion() = 0;

要求的版本是:

    virtual ~criterion()   //Note: Removed void as destructors not allowed 
                             //  a return type

要了解有关虚拟析构函数的更多信息,请查看 FAQ When should my destructor be virtual? 中的此链接

【讨论】:

以上是关于C++ 中的虚拟默认析构函数的主要内容,如果未能解决你的问题,请参考以下文章

具有虚拟析构函数的基类子类中的默认析构函数

C++ 虚拟析构函数 (virtual destructor)

源文件与头文件中的虚拟默认析构函数定义

为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数

C++中的继承和纯虚函数

C++ - 虚拟析构函数和链接器错误