首页 文章

类中的纯虚析构函数定义会产生编译错误

提问于
浏览
13

基类中的 pure virtual destructor 应该有一个定义 . 否则编译器将在链接时生成从派生类析构函数调用基类析构函数,并将导致链接错误 .

我试图在基类中定义纯虚拟析构函数,如下所示:

class base
{
   public:
      base()
      {
         cout << "constructor in base class\n";
      }

      virtual ~base()=0
      {}
};

这给出了编译错误:

error:函数定义的纯指定符

然后我尝试在基类之外定义函数,如下所示:

class base
{
   public:
      base()
      {
         cout << "constructor in base class\n";
      }

      virtual ~base()=0;
};

base::~base()
{

}

这将删除编译错误,它的行为与我的理解相同 .

但我的问题是如何在基类之外定义纯虚拟析构函数来消除编译错误?

5 回答

  • 5

    你的第二个例子是正确的 .

    许多其他答案都假设使用默认实现的纯虚函数是非法的,但这是不正确的 .

    对于纯虚析构函数,您必须有一个定义(请参阅xmoex答案中的link) .

    确实如此:

    §10.4/ 2函数声明不能同时提供纯指定符和定义

    但是,正如您所注意到的那样,可以在声明之外提供定义 .

  • 11

    我看了这个页面:

    http://www.gotw.ca/gotw/031.htm

    从我的理解一个纯虚拟析构函数 must have a definition (甚至是一个空的),因为每个派生类都必须调用基类析构函数

  • 1

    写入的语法无效:

    virtual ~base()=0
    {}
    

    如果要提供纯虚拟成员函数的实现,则应该在类之外执行 . 大多数情况下你不应该这样做,因为永远不应该调用纯虚函数 . 但是,可以定义纯虚函数的实现 .

    实际上,纯虚拟析构函数必须具有实现 . 这是因为无论给定类中的析构函数是否为纯虚拟对象,都会在对象销毁时调用所有基类的析构函数 .

    因此,如果您创建从 base 派生的任何类的实例,那么在某些时候将调用该对象所属的所有类的析构函数,包括 base::~base() 析构函数 . 如果您没有定义它,链接器将找不到所需的符号并会抱怨 .

  • 3

    析构函数是唯一的方法,即使它是纯虚拟的,也必须有一个实现,以便它的类's defined in to be useful. So in contrast to @Kiril'的答案我会说纯虚函数 can 有实现 .

    有点偏离主题:

    struct base {
        virtual void func() = 0;
    };
    
    void base::func() { /* default implementation */ }
    
    class derived : public base{
        void func() { base::func(); } // have to explicitly call default implementation.
    };
    
  • 7

    纯虚方法 can 有实现,但它们使基类抽象并强制派生类来覆盖这些方法 .

    假设您在基类中有一个指针成员 . 您希望在析构函数中删除它,但也使该类抽象 - 因此您实现纯虚拟析构函数 .

    这是一个实现细节 - 实现析构函数的事实不应该从外部可见 .

相关问题