继承,为什么要为基类调用两个构造函数,C ++

时间:2015-12-06 23:09:53

标签: c++ class inheritance constructor

我正在尝试在我的书中做作业,但我不理解输出。当程序中的主代码运行时,输出为:

B :: B(3)

B :: B()//为什么输出

B :: B(-3)

D :: D(3)

首先调用B::B(int n) {},然后调用B::B() {}然后调用接下来的两行来获取此信息。所以程序调用第一个,因为它被声明为函数中的类A的构造函数,它必须赋值,我得到的不是输出行2,为什么B::B() {}甚至被调用?它被称为构造函数,但不应该只是带有参数的构造函数被调用吗?

class B {
public:
    B(); //why is this  called?
    B(int n);
};

// Definitions of B
B::B() { 
    cout << "B::B()\n";
}
B::B(int n) {
    cout << "B::B(" << n << ")\n";
}

class D : public B {
public:
    D();
    D(int n);
private:
    B b;
};

// Definitions of D
D::D() {
    cout << "D::D()\n";
}
D::D(int n) : B(n) {
    b = B(-n);
    cout << "D::D("<< n <<")\n";
}

int main(int argc, const char * argv[]) {
    // insert code here...

    D d(3);
    return 0;    
}

2 个答案:

答案 0 :(得分:3)

首先调用基类构造函数:B::B(3) 然后调用b字段的构造函数:B::B() 然后执行派生的构造函数体(构造所有字段之后) D的构造函数首先在B行上构建另一个b = B(-n);(因此打印B::B(-3)),然后打印D::D(3)

答案 1 :(得分:0)

您的班级D包含两个B类型的对象。

  1. 来自继承的隐式B
  2. 名为B
  3. 的明确b成员

    你可以重写构造函数

    D::D(int n) : B(n)
    {
        b = B(-n);
        cout << "D::D("<< n <<")\n";
    }
    

    D::D(int n) : B(n), b()
    {
        b = B(-n);
        cout << "D::D("<< n <<")\n";
    }
    

    显然B::B()来自何处。因此,您的输出很容易解释:

    B::B(3) // base constructor of `D`
    B::B() // default construction of `b` member
    B::B(-3) // explicit construction inside D::D(int)
    D::D(3) // D::D(int)
    

    如果你写

    D::D(int n) : B(n), b(-n)
    {
        cout << "D::D("<< n <<")\n";
    }
    

    相反,只有

    B::B(3)
    B::B(-3)
    D::D(3)
    

    左侧。

    发表评论:

    想象D看起来像:

    class D : public B
    {
    public:
      D(int);
    };
    

    使用构造函数定义

    D::D(int v) { std::cout << "foo with " << v; }
    

    然后,代码

    D d(3);
    

    打印

    B::B()
    foo with 3
    

    只要B是默认可构造的,它就完全有效。

    如果B缺少默认构造函数,则会出现编译错误,并且您想要将D的定义重写为

    D::D(int v) : B(3) { std::cout << "foo with " << v; }
    

    构造函数初始值设定项列表中的每个直接基类或成员都是默认构造的(如果是类类型),或者在基本类型的情况下保持未初始化。