当一个子类继承了父类后,在子类中如何初始化父类成员?子类中可以定义构造函数,而且必须对继承而来的成员进行初始化,可以直接通过初始化列表或在子类构造时通过给父类成员变量赋值的方式进行初始化父类的成员变量和在子类构造的时候直接调用父类构造函数。但是直接赋值有可能行不通,因为父类的私有成员变量是无法在外界访问的,那么此时就只能通过父类的构造函数来进行初始化工作了,父类构造函数在子类中有两种调用方式,默认调用和显式调用,默认调用适用于无参构造函数或使用了默认参数值的构造函数,当只有一个使用了默认参数值的构造函数时它也会被默认调用,当需要其他参数值的时候默认调用就行不通了,需要显式调用,显式调用是在子类构造函数上通过初始化列表进行调用,适用于所有的父类构造函数。
Child(string s) : Parent(s)
{
cout << "Child(string s) : " << s << endl;
}
在子类中通过初始化列表显式调用父类构造函数。
那么在继承中构造顺序的规则又是什么呢?
子类对象在创建时首先会调用父类的构造函数,再执行子类的构造函数,其中父类构造函数可以被隐式调用或显式调用。
那么当组合和继承一起使用时又有什么新的规则呢?首先先父类后子类这是不会变的,在子类中有其他类对象的构造函数,有自身的构造函数,那么谁先谁后?答案是先调用别的类对象的构造函数再调用自身构造函数。
看一个继承加组合的例子,理解构造调用顺序。
class Object
{
public:
Object(string s)
{
cout << "Object(string s) : " << s << endl;
}
};
class Parent : public Object
{
public:
Parent() : Object("Default")
{
cout << "Parent()" << endl;
}
Parent(string s) : Object(s)
{
cout << "Parent(string s) : " << s << endl;
}
};
class Child : public Parent
{
Object mO1;
Object mO2;
public:
Child() : mO1("Default 1"), mO2("Default 2")
{
cout << "Child()" << endl;
}
Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2")
{
cout << "Child(string s) : " << s << endl;
}
};
main中调用Child cc("construct");语句,结果输出是什么呢?
Object(string s) : construct
Parent(string s) : construct
Object(string s) : construct 1
Object(string s) : construct 2
Child(string s) : construct
顺序就是先父类构造函数,再组合关系中的构造函数,最后自身构造函数。
析构函数的调用顺序呢?
前面说过构造和析构的顺序相反,此处也适用,就是先析构自身,再析构成员变量,最后析构父类。