1

我知道如果 B 是从 A 派生的,那么当我创建 B 的新对象时,例如 b,A 的构造函数将首先调用。当我销毁对象 b 时,B 的析构函数将首先调用。那么我这里有个问题,如果Base类中有多个构造函数,会调用哪个构造函数?为什么?

我在下面写了一个测试程序,我猜它会调用Base类中的默认构造函数,但我不确定这是否只是巧合?

#include <iostream>
using namespace std;

class A{
    public:
    A(int i){cout<<"A con with param"<<endl;}
    A(){cout<<"A con"<<endl;}
    ~A(){}
};

class B : public A
{
    public:
    B(int i){cout<<"B con with param"<<endl;}
    B(){cout<<"B con"<<endl;}
    ~B(){}
};

int main()
{
    B b(5);
    return 0;
}

不知哪位大佬能告诉我这个问题的原因或建议解决这个问题?

4

4 回答 4

3

如果你写:

B(int i) { cout<<"B con with param"<<endl; }

A()然后将调用构造函数(不带参数)。

如果你写:

B(int i): A(i) { cout<<"B con with param"<<endl; }

然后A(int)将调用构造函数。

于 2012-05-10T13:01:30.930 回答
1

编程中没有什么是巧合。
调用默认构造函数是因为您没有将int参数显式传递给基类。

要调用基类的其他构造函数,派生类构造函数需要将参数传递给基类构造函数。
所以A(int)要被调用,你需要有B():A(some_int)B(int):A(some_int)

于 2012-05-10T13:02:34.317 回答
0

除非您在初始化列表中显式调用其他构造函数,否则将调用父类的空构造函数。

编辑:这是显式调用构造函数的方式:

B(int i) : A(i) {
  ... do stuff ...
}
于 2012-05-10T13:03:03.847 回答
0

初始化的顺序比这更复杂一些。从技术上讲,它从最派生对象的初始化列表开始。该构造函数是从创建对象的位置以常规重载分辨率选择的。最派生类型构造函数的初始化列表(显式或隐式)列出了基类的构造函数,并且基类的构造函数将再次使用初始化列表中调用的重载决策来选择。如果初始化列表中没有明确说明基数,编译器将注入对默认构造函数的调用。

构造的确切顺序也有点复杂,因为初始化的第一个子对象是虚拟基,按特定顺序(深度优先,从左到右,从左到右是声明的顺序)基类声明)。一旦所有虚拟基都被初始化,那么最派生类型的直接非虚拟基会被初始化,同样是按照声明的顺序(从左到右)。一旦所有的基都被初始化,成员就会按照类中的声明顺序进行初始化。

请注意,在所有情况下,代码都可以在初始化列表中显式列出子对象,并且将使用其中列出的构造函数,如果实体未列出,则使用默认构造函数。

于 2012-05-10T13:27:10.247 回答