C++中的纯虚析构函数

173

写下这样的代码是有问题的吗:

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

对于一个抽象基类,这样至少可以在MSVC编译通过...但它会在运行时崩溃吗?


11
它可能能够编译,但它能够链接吗? - Mooing Duck
2个回答

229

是的,你还需要实现析构函数:

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

inline A::~A() { }

足以满足需要。

如果你从A中派生任何内容然后尝试删除或破坏它,A的析构函数最终将被调用。由于它是纯虚函数并且没有实现,将导致未定义行为。在某些流行平台上,这将调用purecall处理程序并崩溃。

编辑:修复声明以更符合标准,并使用http://www.comeaucomputing.com/tryitout/编译。


16
是的,的确如此。 "Pure" 只是指一个派生类也需要提供一种实现。 - MSN
78
实现纯虚函数其实是合法的。这对于提供默认实现但强制子类显式调用它非常有用。 - jmucchiello
6
如果您在头文件中有“MSN”和其定义,为避免违反ODR(一个定义规则),您需要在其前面加上“inline”。 - Johannes Schaub - litb
2
如果将调用基类析构函数,那么它必须被定义。如果您从未删除或明确销毁A的子类,则这并不重要。但是如果您这样做了,那么就很重要。 - MSN
11
更好的说法是,一旦您声明了一个析构函数,它并不会自动为您实现。 - MSN
显示剩余8条评论

49
私有析构函数:当您创建派生类的对象时,它们会出现错误,但在其他情况下则不会。尽管可能会出现诊断信息。

12.4 析构函数

6 析构函数可以声明为虚拟的(10.3)或纯虚拟的(10.4);如果该类或任何派生类的对象在程序中被创建,则必须定义析构函数���

具有纯虚拟析构函数的类是抽象类。请注意:

10.4 抽象类

2 只有在使用限定符ID语法(5.1)调用纯虚函数时才需要定义它。

[注意:函数声明不能同时提供纯指示符和定义 - 结束说明]

直接从草案中取出:

struct C {
   virtual void f() = 0 { }; // ill-formed
};

17
我认为Herb Sutter在这方面也有一些很好的信息:http://www.gotw.ca/gotw/031.htm。值得注意的是,任何纯虚函数都可以提供实现,而不仅限于析构函数。 - Fred Larson
6
是的,在面试中这是一种让面试官感到惊讶的做法 ;) - dirkgently
1
根据我的经验,这其实并不是很罕见。 - anon
@Neil Butterworth:哪一个? - dirkgently
@Dirk - “任意函数”场景。在实现一些常见行为时,发现使用它并不罕见。 - anon
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接