为什么只有声明的虚函数会导致编译错误?

Alc*_*ott 14 c++

我有这个班,

class Base {
    public:
        void foo();
};

int main()
{
    Base b;
}
Run Code Online (Sandbox Code Playgroud)

main将编译没有任何错误,虽然foo()没有定义.但是b.foo();会导致编译错误.

此外,即使是constructoroperator=,我就可以宣布他们没有定义它们,只要它会编译,因为我不触发它们.

我再次添加一个虚函数Base,

class Base {
    public:
        void foo();
        virtual void bar();  // no defition is gonna be provided.
};
Run Code Online (Sandbox Code Playgroud)

现在,main无法编译,而是我得到一个错误:

undefined reference to vtable for Base

好吧这让我感到困惑,因为以前main只要foo()没有调用就可以编译,但是现在我添加bar()它并没有被调用.

在这种情况下为什么不编译?

Luc*_*ore 15

这完全取决于编译器.两种情况都不需要诊断.

10.3虚函数[class.virtual]

9 virtual在类中声明的函数应在该类中定义或声明为纯(10.4),或两者兼有; 但不需要诊断 (3.2).[强调我的]

要理解为什么会发生这种情况,让我们来看看它是如何工作的.

每个翻译单元生成一个目标文件,每个目标文件都有导出(它导出的符号)和导入(它想要的符号).

第一个例子很简单 - 导入仅foo在使用时才需要.链接器没有理由查找符号,因此它没有.

第二个,使用该virtual方法,有点复杂.大多数编译器(如果不是全部)都需要有效的虚函数表.这意味着在链接时,声明非纯虚方法的所有类都必须导出这些方法.这比非virtual情况更严格,因为实现实际上并不知道函数是否被调用(它可以被称为多态).


Ben*_*oit 5

第一个版本可以编译,因为链接器不需要搜索对象foo.它无处可用.

但是当你创建一个虚函数时,vtable的构造(用于动态调度)需要一个函数的地址Base::bar(它引用它),因此链接器需要找到它的实现.