#include <iostream.h>
class B1 //基类B1,构造函数有参数
{
public:
B1(int i) {cout <<“constructing B1”<< i << endl;}
};
class B2 //基类B2,构造函数有参数
{
public:
B2(int j) {cout <<“constructing B2”<< j << endl;}
};
class B3 //基类B3,构造函数无参数
{
public:
B3(){cout <<“constructing B3 *”<< endl;}
};
class C:public B2,public B1,public B3
{
public://派生类的公有成员
C(int a,int b,int c,int d):
B1(a),memberB2(d),memberB1(c),B2(b){}
private: //派生类的私有对象成员
B1 memberB1;
B2 memberB2;
B3 memberB3;
};
int main()
{
C obj(1,2,3,4);
return 0;
}
在程序中,派生类C需要声明一个非默认形式(即带参数)的构造函数,因为基类和子对象成员都具有非默认形式的构造函数。这个派生类构造函数的主要功能就是初始化基类和子对象成员,按照前面我们讲的规则,派生类的构造函数定义为:
C(int a,int b,int c,int d):B1(a),memberB2(d),memberB1(c),B2(b) { }
构造函数的参数表中给出了基类及成员对象所需的全部参数,在冒号之后,分别列出了各个基类及子对象名和各自的参数。这里,有几个问题需要注意:首先,这里并没有列出全部基类和成员对象,由于B3类只有默认构造函数,不需要给它传递参数,因此基类B3以及B3类成员对象memberB3就不必列出。其次,基类名和成员对象名的顺序是随意的。这个派生类构造函数的函数体为空,可见实际上只是起到了传递参数和调用基类和子对象构造函数的作用。
程序的主函数中只是声明了一个派生类C的对象c,生成对象c时调用了派生类的构造函数。我们来考虑C类构造函数执行的情况,它应该是先调用基类的构造函数,然后调用子对象成员的构造函数。基类构造函数的调用顺序是按照派生类声明时的顺序,因此应该是先B2,再B1,再B3,而子对象成员的构造函数调用顺序应该是按照成员在类中声明的顺序,应该是先B1,再B2,再B3,程序运行的结果也完全证实了这种分析。
程序的运行结果为:
constructing B2 2
constructing B1 1
constructing B3 *
constructing B1 3
constructing B2 4
constructing B3 *
派生类构造函数声明中,并没有显式列出B3的类名和B3类的对象memberB3,这时系统就会自动调用该类的默认构造函数。如果一个基类同时声明了默认构造函数和带有参数的构造函数,那么在派生类构造函数声明中,既可以显示列出基类名和相应的参数,也可以不列出,程序员可以根据实际情况的需要来自行安排。