C++中,构造函数与父类的其它成员(成员变量和成员方法)不同,它不能被子类继承。因此,在创建子类对象时,为了初始化从父类中继承来的成员变量,编译器需要调用其父类的构造函数。
关于子类中构造函数的构造原则,可分为以下4种情况分别来看:
1. 父类没有声明构造函数
(1) 子类也没有声明自己的构造函数,则父类和子类均由编译器生成默认的构造函数。
(2) 子类中声明了构造函数(无参或者带参),则子类的构造函数可以写成任何形式,不用顾忌父类的构造函数。在创建子类对象时,先调用父类默认的构造函数(编译器自动生成),再调用子类的构造函数。
2. 父类只声明了无参构造函数
如果子类的构造函数没有显式地调用父类的构造,则将会调用父类的无参构造函数。也就是说,父类的无参构造函数将会被隐式地调用。
3. 父类只声明了带参构造函数
因为父类只有带参的构造函数,所以如果子类中的构造函数没有显示地调用父类的带参构造函数,则会报错,所以必需显示地调用。除非父类带参的构造函数的参数有默认值。
//
// test_extend.cpp
// TestProject
//
#include <stdio.h>
#include <iostream>
using namespace std;
class SuperClass1
{
public:
SuperClass1(int i){
cout<<"Constructing SuperClass with param i "<<i<< endl;
}
};
class SubClass :public SuperClass1
{
public:
//compile error,Constructor for 'SubClass' must explicitly initialize the base class 'SuperClass1' which does not have a default constructor
//SubClass(int i){}
//compile ok
SubClass(int i):SuperClass1(i){}
};
int main()
{
SubClass s(3);
}
运行结果如下:
Constructing SuperClass with param i 3
Program ended with exit code: 0
4. 父类同时声明了无参和带参构造函数
在这种情况下,子类只需要实现父类的一个构造函数即可,不管是无参的还是带参的构造函数。
如果子类的构造函数没有显示地调用父类的构造函数(无参或带参),则默认调用父类的无参构造函数。
子类当然也可以显式调用父类的带参构造函数
//
// test_extend.cpp
// TestProject
//
#include <stdio.h>
#include <iostream>
using namespace std;
class SuperClass1
{
public:
SuperClass1(){
cout<<"Constructing SuperClass no param "<<endl;
}
SuperClass1(int i){
cout<<"Constructing SuperClass with param i "<<i<< endl;
}
};
class SubClass :public SuperClass1
{
public:
//compile error,Constructor for 'SubClass' must explicitly initialize the base class 'SuperClass1' which does not have a default constructor
SubClass(){}
//compile ok
SubClass(int i):SuperClass1(i){}
};
int main()
{
SubClass s;
SubClass s2(3);
}
运行结果如下:
Constructing SuperClass no param
Constructing SuperClass with param i 3
Program ended with exit code: 0
初始化过程中,初始化的执行顺序是:
1.先调用基类构造器,初始化基类成员。调用顺序按照它们被继承时的顺序(从左至右)
2.再找初始化列表指定的初始化子类新成员对象。调用顺序按照它们在类中声明的顺序,与构造函数初始化列表里的书写顺序无关
3.最后才执行子类构造器中的函数体
其中,如果派生类中新增成员中有内嵌的对象,第二步调用才会执行,否则,就直接跳转到第三步。
//
// test_extend.cpp
// TestProject
//
#include <stdio.h>
#include <iostream>
using namespace std;
class SuperClass1
{
public:
SuperClass1(int i){
cout<<"Constructing SuperClass 1 "<<i<< endl;
}
};
class SuperClass2
{
public:
SuperClass2(int j){
cout<<"Constructing SuperClass 2 "<<j<< endl;
}
};
class SuperClass3
{
public:
SuperClass3(){
cout<<"Constructing SuperClass 3 "<< endl;
}
};
class SubClass : public SuperClass2,public SuperClass1,public SuperClass3
{
public:
SubClass(int a,int b, int c,int d):SuperClass1(a),s2(d),s1(c),SuperClass2(b){
i = 100;
cout<<"Constructing SubClass i "<< i << endl;
}
private:
SuperClass1 s1;
SuperClass2 s2;
SuperClass3 s3;
int i;
};
int main()
{
//1.SubClass从左到右依次继承了SuperClass2,SupClass1,SuperClass3,所以先执行SuperClass2的构造函数(SuperClass2(b)),然后执行SuperClass3的构造函数(默认构造函数),然后执行SuperClass1的构造函数(SuperClass1(a))
//2.再执行成员变量的初始化,先是s1(s1(c)),然后s2(s2(b)),最后s3,由于s3成员变量对应的类是默认构造函数,所以不需要传参数,s1,s2都必须在SubClass的构造函数初始化列表中,显示初始化
//3.最后执行构造函数体中的代码,i=100
SubClass obj(1,2,3,4);
return 0;
}
执行结果:
Constructing SuperClass 2 2
Constructing SuperClass 1 1
Constructing SuperClass 3
Constructing SuperClass 1 3
Constructing SuperClass 2 4
Constructing SuperClass 3
Constructing SubClass i 100
Program ended with exit code: 0
参考链接: