C++ 是否应该定义基本dtor?

C++ 是否应该定义基本dtor?,c++,C++,编译器给出了链接错误,需要为基纯虚拟析构函数提供定义 class Base { public: virtual ~Base() = 0; }; class Derived : public Base { public: virtual ~Derived(){ std::cout << "Derived dtor"; } }; int main() { Derived d; } 类基 { 公众: virtual~Base()=0; }; 派生类:公共

编译器给出了链接错误,需要为基纯虚拟析构函数提供定义

class Base
{
public:
    virtual ~Base() = 0;
};

class Derived : public Base
{
public:
    virtual ~Derived(){ std::cout << "Derived dtor"; }
};

int main()
{
       Derived d;
}
类基
{
公众:
virtual~Base()=0;
};
派生类:公共基
{
公众:

virtual~Derived(){std::cout只需为其提供一个空实现(在类定义之外):

纯虚拟只是意味着您必须重写任何具体派生类中的成员函数;这并不意味着它不能有主体。对于析构函数,无论析构函数是否纯虚拟,您都必须提供主体,因为它是在销毁对象时由编译器调用的

需要明确的是,您必须提供一个实现。它是否为空取决于您。这是因为每当您尝试销毁Base实例时,编译器都会生成调用析构函数的代码。您可以声明一个正常的虚拟Base:

virtual ~Base();

并且永远不要定义它。只要你不销毁Base的实例就可以了(行为可疑,但它可以工作)。但是,在你的情况下,Base有一个派生类型,它在自己的析构函数中调用基类的析构函数。这就是你的链接器错误的来源。

只需为它提供一个空的实现(在类别定义之外):

纯虚拟只是意味着您必须重写任何具体派生类中的成员函数;这并不意味着它不能有主体。对于析构函数,无论析构函数是否纯虚拟,您都必须提供主体,因为它是在销毁对象时由编译器调用的

需要明确的是,您必须提供一个实现。它是否为空取决于您。这是因为每当您尝试销毁Base实例时,编译器都会生成调用析构函数的代码。您可以声明一个正常的虚拟Base:

virtual ~Base();

并且永远不要定义它。只要你不破坏一个Base实例(有问题的行为,但它会起作用),这就可以了但是,在您的情况下,Base有一个派生类型,它在自己的析构函数中调用基类的析构函数。这就是链接器错误的来源。

由于
Derived
继承
Base
,因此销毁
Derived
对象将首先调用
Derived:~Derived
,然后
Base:~Base
(不管您喜欢与否,编译器都会为您执行此操作)


因此,您必须为
Base::~Base
提供一个实现。请注意,这并不特别奇怪。纯虚拟函数可以有一个实现。“纯虚拟”只意味着类不能实例化。

因为
派生的
继承
基础的
,所以销毁
派生的
对象将首先失败t调用
Derived::~Derived
,然后调用
Base::~Base
(不管您喜欢与否,编译器都会为您执行此操作)



因此,您必须为
Base::~Base
提供一个实现。请注意,这并不特别奇怪。纯虚拟函数可以有一个实现。“纯虚拟”只意味着类不能实例化。

是的。有一个非虚拟调用
Base::~Base
,隐式来自
派生::~Derived
因此,编译器有权抱怨必须定义
Base::~Base
,即使是空的。

是的。有一个非虚拟调用
Base::~Base
,隐式地来自
派生::~Derived
。因此编译器有权抱怨必须定义
Base::~Base
,即使是空的。

你的意思是
virtual~Base(){}
;)@Mephane:我是说我写的。如果你读了我其余的答案,它会更有意义。~Base不是已经是纯虚拟的吗?为什么我应该提供一个空的实现?@Noro:Marcelo给出了你应该(实际上,为什么你必须)的原因提供一个实现。不管您喜欢与否,编译器都会调用该函数,因此您必须提供一个实现。此语法似乎无效。纯虚拟函数必须在类之外实现(不重复
=0
),您的意思是
virtual~Base(){}
;)@梅芬:我是说我写的。如果你读了我其余的答案,它会更有意义。~Base不是已经是纯虚拟的吗?为什么我应该提供一个空的实现?@Noro:Marcelo给出了你应该(实际上,为什么你必须)的原因提供一个实现。无论您喜欢与否,编译器都会调用该函数,因此您必须提供一个实现。此语法似乎无效。纯虚拟函数必须在类之外实现(不重复
=0
)事实上,正如Marcelo Cantos在他的回答中所写,纯虚拟意味着必须在非抽象的子类中重写函数。@Gorpik:这显然是多余的:当然,它必须在想要非抽象的类中重写。“抽象”是根据类是否具有纯虚拟方法来定义的。从某种意义上说,你是机器人h对。纯虚方法意味着类不能被实例化,这当然意味着派生类必须重写它才能被实例化。@Gorpik:而且类将隐式地具有析构函数,派生类不需要显式重写析构函数。-纯虚析构函数只在不允许基被实例化(假定该基没有其他要成为纯函数的函数)实际上,正如马塞洛·坎托斯(Marcelo Cantos)在他的回答中所说,纯虚拟意味着必须在非抽象的子类中重写函数。@Gorpik:这显然是多余的:当然,它必须在想要非抽象的类中重写。“抽象”是根据类是否是否有纯虚拟方法。在某种程度上,你们都是对的。纯虚拟方法意味着类无法实例化,这当然意味着