C++访谈继承之谜

sam*_*tha 2 c++ inheritance

可能重复:
构造函数中的C++虚函数
调用构造函数内的虚函数

在采访中询问了这个问题.

我想我已经正确回答了第一部分但不确定第二部分.事实上,我对第二部分毫无头绪.

  1. 以下代码生成什么输出?为什么?
  2. 如果使A :: Foo()成为纯虚函数,它会产生什么输出?

当我尝试在我的编译器上运行相同的问题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)

Ker*_* SB 8

实例化B对象时,会发生以下情况:

  1. B的构造函数被调用.

  2. 首先,B构造函数调用基础构造函数A().

  3. 在里面A的构造函数中,调用了函数调用A::foo(),因为它this有静态动态类型A*(如果你考虑它就没有其他意义); 现在A子对象已完成.

  4. 现在B的构造函数体运行了.这里调用函数调用B::foo().现在整个B对象都已完成.

如果A::foo()是纯虚拟,则步骤(3)导致未定义的行为 ; 比照 标准中为10.6/4.

(在您的情况下可能表现为链接器错误,因为编译器会优化以静态解析调用,并且A::foo找不到符号.)


Che*_*Alf 5

在第二种情况下,您有未定义的行为(在类 T 构造函数中调用类 T 的纯虚拟),因此输出可以是任何内容 - 如果它甚至可以编译的话。

主要要理解的是,在C++中,当对象的T构造函数执行时,对象的动态类型是T。

这使得从 C++ 构造函数调用虚函数变得安全。您不会调用未初始化的派生类子对象。相比之下,在 Java 和 C#(以及类似的语言)中,您很容易遇到这种错误,而且很常见。