【C++笔记】C++继承与派生中的构造函数

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

参考链接:

https://blog.csdn.net/sevenjoin/article/details/82222895

https://www.jianshu.com/p/6cabb9e27d58

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值