C ++访谈继承之谜

时间:2011-11-28 22:32:10

标签: c++ inheritance

  

可能重复:
  C++ virtual function from constructor
  Calling virtual functions inside constructors

这个问题在采访中被问到了。

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

  1. 以下代码生成什么输出?为什么?
  2. 如果使A :: Foo()成为纯虚函数,它会产生什么输出?
  3. 当我尝试使用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;
    }
    

4 个答案:

答案 0 :(得分:8)

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

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

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

  3. A的构造函数中,函数调用被调度到A::foo(),因为this具有静态动态类型{{1} (如果你想的话,别无其他意义);现在A*子对象已完成。

  4. 现在A的构造函数体已运行。这里函数调用被分派到B。现在整个B::foo()对象已完成。

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

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

答案 1 :(得分:4)

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

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

这使得从C ++构造函数调用虚函数变得安全。您没有调用未初始化的派生类子对象。相比之下,在Java和C#(以及类似语言)中,您可以轻松获得这种错误,这很常见。

干杯&amp;第h。,

答案 2 :(得分:1)

构造函数中的方法被调度为类的动态类型。 A的构造函数用动态类型A调用Foo。(参见AlfP.Steinbach对正确定义的评论)

如果A是抽象基础,那么错误是因为它试图调用纯虚方法。

A()             
{
    this->Foo(); // call A::Foo
}

来自Scott Meyers的Effective C ++:

  

这种看似违反直觉的行为有充分的理由。因为基类构造函数在派生类构造函数之前执行,所以在基类构造函数运行时尚未初始化派生类数据成员。如果在基类构造期间调用的虚函数归结为派生类,派生类函数几乎肯定会引用本地数据成员,但这些数据成员尚未初始化。这将是未定义行为和深夜调试会话的直接票。调用尚未初始化的对象的某些部分本质上是危险的,因此C ++让你无法做到。

答案 3 :(得分:1)

将调用构造函数,以便首先构造父类,以便不会对未定义的对象产生任何依赖。因此它是A :: A,然后是B :: B.编辑:B的构造函数也可能直接调用A,如Kerrek SB says - 最终效果是相同的。

在第一种情况下,输出将是“A :: Foo()”,后跟“B :: Foo()”。在A的构造时B还不存在,其虚函数还不是对象的一部分。

在第二种情况下,您将调用纯虚函数A :: Foo,它将生成错误或拒绝完全编译。

相关问题