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:这显然是多余的:当然,它必须在想要非抽象的类中重写。“抽象”是根据类是否是否有纯虚拟方法。在某种程度上,你们都是对的。纯虚拟方法意味着类无法实例化,这当然意味着