基类中的 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 回答
你的第二个例子是正确的 .
许多其他答案都假设使用默认实现的纯虚函数是非法的,但这是不正确的 .
对于纯虚析构函数,您必须有一个定义(请参阅xmoex答案中的link) .
确实如此:
但是,正如您所注意到的那样,可以在声明之外提供定义 .
我看了这个页面:
http://www.gotw.ca/gotw/031.htm
从我的理解一个纯虚拟析构函数 must have a definition (甚至是一个空的),因为每个派生类都必须调用基类析构函数
写入的语法无效:
如果要提供纯虚拟成员函数的实现,则应该在类之外执行 . 大多数情况下你不应该这样做,因为永远不应该调用纯虚函数 . 但是,可以定义纯虚函数的实现 .
实际上,纯虚拟析构函数必须具有实现 . 这是因为无论给定类中的析构函数是否为纯虚拟对象,都会在对象销毁时调用所有基类的析构函数 .
因此,如果您创建从
base
派生的任何类的实例,那么在某些时候将调用该对象所属的所有类的析构函数,包括base::~base()
析构函数 . 如果您没有定义它,链接器将找不到所需的符号并会抱怨 .析构函数是唯一的方法,即使它是纯虚拟的,也必须有一个实现,以便它的类's defined in to be useful. So in contrast to @Kiril'的答案我会说纯虚函数 can 有实现 .
有点偏离主题:
纯虚方法 can 有实现,但它们使基类抽象并强制派生类来覆盖这些方法 .
假设您在基类中有一个指针成员 . 您希望在析构函数中删除它,但也使该类抽象 - 因此您实现纯虚拟析构函数 .
这是一个实现细节 - 实现析构函数的事实不应该从外部可见 .