【问题标题】:Virtual Default Destructors in C++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 是否也需要一个虚拟析构函数?

【问题讨论】:

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

标签: c++ virtual-destructor


【解决方案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? 中的此链接

    【讨论】:

      猜你喜欢
      • 2017-04-21
      • 2014-01-30
      • 1970-01-01
      • 2011-09-30
      • 2016-03-26
      • 2012-07-14
      • 2018-06-29
      • 2011-08-12
      • 1970-01-01
      相关资源
      最近更新 更多