基类中的pure virtual destructor
应该有一个定义。否则编译器将在链接时从链接派生类析构函数生成对基类析构函数的调用,并将导致链接错误。
我尝试在基类中定义纯虚拟析构函数,如下所示:
class base
{
public:
base()
{
cout << "constructor in base class\n";
}
virtual ~base()=0
{}
};
这给出了编译错误:
错误:函数定义上的纯指定符
然后我尝试在基类之外定义函数,如下所示:
class base
{
public:
base()
{
cout << "constructor in base class\n";
}
virtual ~base()=0;
};
base::~base()
{
}
这会删除编译错误,它的行为与我的理解相同。
但我的问题是如何在基类之外定义纯虚析构函数来消除编译错误?
答案 0 :(得分:11)
你的第二个例子是正确的。
许多其他答案都假设使用默认实现的纯虚函数是非法的,但这是不正确的。
对于纯虚拟析构函数,您必须有一个定义(请参阅xmoex答案中的link)。
确实如此:
§10.4/ 2函数声明不能同时提供纯指定符 和定义
但是,您注意到可以在声明之外提供定义。
答案 1 :(得分:7)
答案 2 :(得分:5)
写入语法无效:
virtual ~base()=0
{}
如果要提供纯虚拟成员函数的实现,则应该在类之外执行。大多数情况下你不应该这样做,因为永远不应该调用纯虚函数。但是,可以为纯虚函数定义实现。
实际上,纯虚拟析构函数必须具有实现。这是因为无论给定类中的析构函数是否为纯虚拟对象,都会在对象销毁时调用所有基类的析构函数。
因此,如果您创建从base
派生的任何类的实例,那么在某些时候将调用该对象所属的所有类的析构函数,包括base::~base()
析构函数。如果您没有定义它,链接器将找不到所需的符号并且会抱怨。
答案 3 :(得分:3)
析构函数是唯一的方法,即使它是纯虚方法,也必须有一个实现,以便它定义的类有用。因此,与@ Kiril的答案相反,我会说纯虚函数可以实现。
有点偏离主题:
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.
};
答案 4 :(得分:1)
纯虚方法可以具有实现,但是它们使基类成为抽象,并强制派生类来覆盖这些方法。
假设您在基类中有一个指针成员。你想在析构函数中删除它,但也使类抽象 - 所以你实现了纯虚析构函数。
这是一个实现细节 - 实现析构函数的事实不应该从外部可见。