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:我不是在提倡那篇文章中讨论的修复方法,我只是认为它包含了一些有趣的信息。我会对实现纯虚拟函数保持警惕,因为它可能会让人困惑。