可能重复:
构造函数中的C++虚函数
调用构造函数内的虚函数
在采访中询问了这个问题.
我想我已经正确回答了第一部分但不确定第二部分.事实上,我对第二部分毫无头绪.
当我尝试在我的编译器上运行相同的问题virtual void foo() = 0;时抛出错误"未定义引用`A :: Foo()'"
#include <iostream>
using namespace std;
class A
{
public:
A()
{
this->Foo();
}
virtual void Foo()
{
cout << "A::Foo()" << endl;
}
};
class B : public A
{
public:
B()
{
this->Foo();
}
virtual void Foo()
{
cout << "B::Foo()" << endl;
}
};
int main(int, char**)
{
B objectB;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
实例化B对象时,会发生以下情况:
B的构造函数被调用.
首先,B构造函数调用基础构造函数A().
在里面A的构造函数中,调用了函数调用A::foo(),因为它this有静态和动态类型A*(如果你考虑它就没有其他意义); 现在A子对象已完成.
现在B的构造函数体运行了.这里调用函数调用B::foo().现在整个B对象都已完成.
如果A::foo()是纯虚拟,则步骤(3)导致未定义的行为 ; 比照 标准中为10.6/4.
(在您的情况下可能表现为链接器错误,因为编译器会优化以静态解析调用,并且A::foo找不到符号.)
在第二种情况下,您有未定义的行为(在类 T 构造函数中调用类 T 的纯虚拟),因此输出可以是任何内容 - 如果它甚至可以编译的话。
主要要理解的是,在C++中,当对象的T构造函数执行时,对象的动态类型是T。
这使得从 C++ 构造函数调用虚函数变得安全。您不会调用未初始化的派生类子对象。相比之下,在 Java 和 C#(以及类似的语言)中,您很容易遇到这种错误,而且很常见。