在什么条件下生成纯虚方法存根?

时间:2017-09-15 15:45:25

标签: c++ gcc

我已经在许多地方(例如here)阅读了关于人们获得一个名为"的纯虚拟方法的问题。 运行时时出错和程序崩溃。 This answer

  

大多数编译器将这样的vtable条目分配给存根,该存根在中止程序之前发出错误。

this one甚至说Itanium ABI指定了该存根的内容。

问题是:我在编辑器(GCC 6.4.1)在编译时中捕获的所有尝试都是未定义的引用。例如,当从抽象类的构造函数调用纯虚函数时,我会收到警告

pure virtual ‘virtual int X::f()’ called from constructor

但同时根本没有为X::f()生成任何代码,所以接下来是

undefined reference to 'X::f()'

来自链接器的

并且编译失败。这似乎是一种在运行时防止错误的非常简单的方法。在哪种情况下,我的编译器实际上需要生成上述存根?或者它是否足够聪明,足以及早发现所有可能的病理情况?

1 个答案:

答案 0 :(得分:10)

通常它会在构造函数中间接调用。这是一个最小的例子:

#include <iostream>

struct X {
    virtual void foo() = 0;
    void bar() { foo(); }
    X() { bar(); std::cout << "X"; }
};

struct Y : X {
    void foo() override {}
};


int main() {
    Y y;
    return 0;
}

如果编译器直接出现在c内,则编译器必须静态绑定调用(因此可以为纯虚函数生成有用的错误消息)。但是当调用是间接的,来自另一个成员时,必须动态调度它。

当然,Y部分在X的构造过程中尚未构建,因此整个事物在未定义的行为中坍塌。

Live example - With the stub at work