为什么这不是纯虚函数的调用?

Why is this not a call of a pure virtual function?

我尝试 "repair" this answer 中的示例来演示如何调用纯虚函数。

#include <iostream>
using namespace std;

class A
{
    int id;
public:
    A(int i): id(i) {}
    int callFoo() { return foo(); }
    virtual int foo() = 0;
};

class B: public A
{
public:
    B(): A(callFoo()) {}
    int foo() { return 3; }
};

int main() {
    B b; // <-- this should call a pure virtual function
    cout << b.callFoo() << endl;
    return 0;
}

但是我没有得到运行时错误here (with C++ 4.9.2),但是输出了 3。我在 Borland C++ 5.6.4 中尝试了同样的方法,但是我遇到了访问冲突。我认为foo()在基础class.

的构造函数调用中应该是纯虚的

谁错了?我应该尝试更多的编译器吗?我对虚函数的理解是否正确?

语句B b;调用默认构造函数B

构造 B 时,在完全构造 A 之前,不会构造任何与 B 相关的内容。

所以在尝试调用 callFoo() 时,行为是未定义的,因为您不能依赖 v-table 来设置 class B

总结:在构造抽象class期间调用纯虚函数的行为是未定义的。

您的代码有未定义的行为:在对象的所有基 类 初始化之前调用对象(即使是非虚拟对象)的成员函数是 UB。 C++14 (n4140) 12.6.2/14,强调我的:

Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of the typeid operator (5.2.8) or of a dynamic_cast (5.2.7). However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined. ...

ctor-initializer: 之后的整个列表。 mem-initializer 是该列表的一个元素。