C++ 为什么这不是一个纯虚函数的调用?

C++ 为什么这不是一个纯虚函数的调用?,c++,pure-virtual,C++,Pure Virtual,我试图“修复”中的示例,以演示如何调用纯虚函数 #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()) {} i

我试图“修复”中的示例,以演示如何调用纯虚函数

#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;
}
#包括
使用名称空间std;
甲级
{
int-id;
公众:
A(inti):id(i){}
int callFoo(){return foo();}
虚拟int foo()=0;
};
B类:公共A
{
公众:
B():A(callFoo()){}
int foo(){return 3;}
};
int main(){

B;//语句
B;
将默认构造函数调用为
B

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

因此,在尝试调用
callFoo()
时,行为是未定义的,因为您不能依赖于正在设置的类
B
的v表


总而言之:在构造抽象类的过程中调用纯虚函数的行为是未定义的。

您的代码具有未定义的行为:在初始化对象的所有基类之前调用对象上的成员函数(即使是非虚函数)是不可能的。C++14(n4140)12.6.2/14,重点是:

可以为正在构造的对象调用成员函数(包括虚拟成员函数,10.3)。 类似地,正在构造的对象可以是
typeid
运算符(5.2.8)或
动态转换(5.2.7)的操作数。但是,如果这些操作在ctor初始值设定项中执行(或在直接调用的函数中执行)
或间接从ctor初始值设定项)在所有基类的mem初始值设定项完成之前,结果
未定义操作的名称。


cter初始化器是下面的代码列表::MEM初始化器是这个列表的一个元素。

我不使用Borland C++的测试结果来查看代码的片段是否有效和/或符合标准;)CorykRAMER虚拟函数现在使用了几十年。我知道这一点,我做了一个厚颜无耻的评论。有人仍然在使用Borland IDEs;-)只有在我必须的时候,不幸的是,情况仍然如此。我认为你在用未定义的行为跳舞。如果你看看我,我在
a::callFoo()中添加
cout
语句时出现了分段错误
。如果我们删除
cout
语句,那么它就会编译并工作。我不得不猜测,最简单的示例恰好在指针保持对齐时工作。我猜是这样的,因为。因此,我的“修复”似乎有点懒惰建议。是的,这条UB规则是有根据的。但这只会让人头痛-没有编译器或静态代码检查器会发现所有错误。我很震惊,这样简单的内联案例没有立即被拒绝。@Wolf:编译器,因为这可能不可能在编译时静态执行。@Kevin实现纯虚拟函数对我来说,删除名为messages的纯虚拟函数似乎是误用,或者它正是为了这个目的而设计的?@Wolf:我不是在提倡那篇文章中讨论的修复方法,我只是认为它包含了一些有趣的信息。我会对实现纯虚拟函数保持警惕,因为它可能会让人困惑。