我知道如果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;
}
我想知道是否有老板可以告诉我原因或任何建议来解决这个问题?
答案 0 :(得分:3)
如果你写:
B(int i) { cout<<"B con with param"<<endl; }
然后将调用构造函数A()
(不带参数)。
如果你写:
B(int i): A(i) { cout<<"B con with param"<<endl; }
然后将调用构造函数A(int)
。
答案 1 :(得分:1)
编程中没有巧合
调用默认构造函数是因为您未将int
参数显式传递给基类。
对于要调用的其他基类构造函数,派生类构造函数需要将参数传递给基类构造函数。
因此,要调用A(int)
,您需要B():A(some_int)
或B(int):A(some_int)
答案 2 :(得分:0)
除非在初始化列表中显式调用其他构造函数,否则将调用父类的空构造函数。
编辑:这是你如何明确地调用构造函数:
B(int i) : A(i) {
... do stuff ...
}
答案 3 :(得分:0)
初始化的顺序比这更令人费解。从技术上讲,它从最多派生对象的初始化列表开始。从创建对象的位置开始,使用常规重载决策选择该构造函数。 大多数派生的类型构造函数的初始化列表(显式地或隐式地)列出基础的构造函数,并且将再次使用初始化列表中的调用的重载解析来选择基础的构造函数。如果未在初始化列表中明确声明基类,则编译器将注入对默认构造函数的调用。
构造的确切顺序也有点复杂,因为初始化的第一个子对象是虚拟基础,按特定顺序(深度优先,从左到右,从左到右为顺序)声明中的声明)。一旦初始化了所有虚拟基础,则再次按声明的顺序(从左到右)初始化最派生类型的直接非虚拟基础。初始化所有碱基后,然后按类中的声明顺序初始化成员。
请注意,在所有情况下,代码都可以在初始化列表中显式列出子对象,并且将使用其中列出的构造函数,如果未列出实体,则使用默认构造函数。