我试图在这个答案中 "修复"这个例子,以演示如何调用纯虚函数.
#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;
}
Run Code Online (Sandbox Code Playgroud)
但是我没有得到运行时错误(使用C++ 4.9.2),但输出3.我尝试使用Borland C++ 5.6.4,但是我遇到了访问冲突.我认为foo()在基类的构造函数的调用中应该是纯虚拟的.
谁错了?我应该尝试更多的编译器吗?我是否正确理解虚函数?
Rei*_*ica 14
您的代码具有未定义的行为:在初始化所有基类之前,在对象(甚至是非虚拟对象)上调用成员函数是UB.C++ 14(n4140)12.6.2/14,强调我的:
可以为正在构造的对象调用成员函数(包括虚拟成员函数,10.3).类似地,正在构造的对象可以是运算
typeid符(5.2.8)或dynamic_cast(5.2.7)的操作数.但是,如果在基类的所有mem-initializer完成之前,在ctor-initializer(或直接或间接从ctor-initializer调用的函数)中执行这些操作,则操作的结果是不确定的....
ctor-initializer是以下的完整列表:.mem-initializer是此列表的一个元素.
该语句B b;调用默认构造函数B.
在构建时B,在完全构造B之前不构造任何相关的东西A.
因此,在尝试调用时callFoo(),行为是未定义的,因为您不能依赖v-table来B设置类.
总结:在构造抽象类期间调用纯虚函数的行为是未定义的.