18.继承后的构造函数和析构函数

18.面向对象-继承-继承后的构造函数和析构函数


18.1 知识点

继承中的构造函数

执行顺序

  • 当子类实例化(进行构造)时,构造函数的执行顺序如下:

    1. 先执行父类构造函数(按继承顺序)
    2. 再执行子类中成员对象的构造函数(按声明顺序)
    3. 最后执行子类自身的构造函数体
  • 可总结为:先父后子内,子内结束最后子

  • 实际观察一个例子,可以发现:
    首先执行父类构造函数
    然后是子类中成员对象的构造函数
    最后才是子类本身的构造函数体



  • 多重继承情况下也是如此。
    即:有祖父类 → 父类再加一个成员对象,构造时依然满足以上规则。


基类构造的调用方式

  • 默认情况下,子类构造函数会自动调用父类的无参构造函数

  • 如果父类没有无参构造函数,子类必须显式调用父类的带参构造函数
    否则会出现编译错误

  • 举例说明:

    • 假设祖父类的构造函数有参数,顶掉了默认无参构造函数
    • 那么在父类构造函数中必须显式调用祖父类构造传参
    • 否则在子类中也会因为找不到合适的祖先构造方式而报错



继承中的析构函数

执行顺序

  • 当子类被销毁(进行析构)时,析构函数的执行顺序如下:

    1. 先执行子类析构函数
    2. 再析构子类成员对象
    3. 最后执行父类析构函数
  • 可总结为:先子后子内,子内结束最后父

实例





构造函数和析构函数不能被继承

  • 构造函数和析构函数不会被子类继承

  • 举例:

    s.Test(); // 这是一个普通函数,在父类实现,子类可以直接调用
    
    // Son s2 = Son(10); // 报错:因为父类中有有参构造,而子类没有提供构造函数
    // 构造函数不能被继承,因此不能直接使用父类的构造方式创建子类对象
    
  • 如果希望在子类中使用父类构造函数,可以使用 using 显式引入父类的构造函数:

    using 父类名::父类名;
    

    它的作用是让子类中拥有与父类相同的构造函数

  • 注意事项:

    • using 的方式仅适用于构造函数
    • 析构函数不适用该方式,因为析构函数规则是固定的,且不带参数

实例



总结

  • 构造函数与析构函数在继承中的执行顺序:

    • 构造时顺序:父类 → 子类成员对象 → 子类本身
    • 析构时顺序:子类 → 子类成员对象 → 父类
  • 默认调用的父类构造函数是无参构造
    如果父类中没有无参构造,则需要子类中显式调用带参构造函数

  • 构造函数和析构函数不能被继承

    • 若要在子类中使用和父类一样的构造函数
      必须使用 using 父类名::父类名 引入

18.2 知识点代码

GrandPa.h

#pragma once
#include <iostream>
using namespace std;
class GrandPa
{
public:
    GrandPa(int i)
    {
        cout << "GrandPa构造" << i << endl;
    }
    ~GrandPa()
    {
        cout << "GrandPa析构" << endl;
    }
};

Father.h

#pragma once
#include "GrandPa.h"
#include "Other.h"
class Father : public GrandPa
{
public:
    Other other1;

    Father(int i) : GrandPa(i)
    {
        cout << "Father1个参数的构造" << endl;
    }

    Father(int i, int j) : GrandPa(i)
    {
        cout << "Father2个参数的构造" << endl;
    }

    ~Father()
    {
        cout << "Father析构" << endl;
    }

    void Test()
    {

    }
};

Son.h

#pragma once
#include "Father.h"
#include "Other.h"
class Son : public Father
{
public:
    Other other2;
    using Father::Father;
    Son() : Father(99)
    {
        cout << "Son构造" << endl;
    }

    ~Son()
    {
        cout << "Son析构" << endl;
    }
};

Other.h

#pragma once
#include <iostream>
using namespace std;
class Other
{
public:
    Other()
    {
        cout << "Other构造" << endl;
    }

    ~Other()
    {
        cout << "Other析构" << endl;
    }
};

Lesson18_面向对象_继承_继承后的构造函数和析构函数.cpp

#include <iostream>
#include "Son.h"
int main()
{
    #pragma region 知识点一 继承中的构造函数

    #pragma region 执行顺序
    //在子类进行构造时(实例化时),构造函数的执行顺序是
    //1.按照继承顺序,先执行父类构造函数
    //2.再按照声明顺序 执行成员对象的构造函数
    //3.最后执行子类自己的构造函数体

    //先父后子内,子内结束最后子
    Son s;
    #pragma endregion

    #pragma region 基类构造的调用方式
    //在自动执行父类构造函数时,默认调用的是父类的无参构造函数
    //如果父类没有无参构造函数,子类必须显示调用带参构造函数
    //否则会报错
    #pragma endregion

    #pragma endregion

    #pragma region 知识点二 继承中的析构函数

    #pragma region 执行顺序
    //在子类进行析构时(销毁时),析构函数的执行顺序是
    //1.先执行子类析构
    //2.再析构成员对象
    //3.最后析构父类对象

    //先子后子内,子内结束最后父
    #pragma endregion

    #pragma endregion

    #pragma region 知识点三 构造函数和析构函数不能被继承
    //构造函数和析构函数不会被子类继承
    //比如:父类中有一个有参构造函数
    //     但是我们在子类中是不能使用的

    s.Test();//这个Test是普通函数 是在父类实现的 子类可以随便调
    //Son s2 = Son(10);//报错
    //父类中有一个有参构造函数  子类没有有参构造函数 会报错 因为构造函数不能被继承

    //如果我们想要在子类中能够直接使用父类中的构造
    //我们可以通过using关键字,显示的引入基类的构造函数
    // 语法:using 父类名::父类名;
    //它的作用相当于让子类中多了和父类一模一样的构造函数

    //注意:只针对构造函数而言,析构函数不存在这样的做法,因为析构函数的规则是固定的,无参

    //在子类添加了	using Father::Father; 可以使用父类父类的有参构造函数了
    Son s2 = Son(10);
    Son s3 = Son(1, 3);

    #pragma endregion

    //总结
    //1.构造函数和析构函数在继承中的执行顺序
    //  父-子内-子      子-子内-父
    //2.默认调用的父类的构造是无参构造,如果父类中没有了,需要显示调用其他构造
    //3.构造函数和析构函数不能被继承
    //	如果想要在子类中使用和父类结构一样的构造函数 需要使用 using 父类名::父类名

}

18.3 练习题

有一个打工人基类,有工种、工作内容两个特征,一个工作方法;程序员、策划、美术分别继承打工人,请用继承中的构造函数知识点实例化三种对象

有一个基类 Worker,包含两个成员变量 type(工种)和 content(工作内容),以及一个成员方法 Work()
三种子类 ProgrammerPlanArt 分别在其构造函数中调用基类构造函数,传入对应的工种和工作内容。

#pragma once
#include <iostream>
using namespace std;

class Worker
{
public:
    string type;     // 工种
    string content;  // 工作内容
    Worker(string type, string content) : type(type), content(content) {};
    void Work();
};
#include "Worker.h"

void Worker::Work()
{
    cout << "职位:" < 
    #pragma once
    #include "Worker.h"
    class Art : public Worker
    {
    public:
        Art() : Worker("美术", "画图建模设计UI")
        {
        }
    };

    < type << " 工作内容:" << content << endl;
}
#pragma once
#include "Worker.h"
class Plan : public Worker
{
public:
    Plan() : Worker("策划", "设计游戏")
    {
    }
};
#pragma once
#include "Worker.h"
class Programmer : public Worker
{
public:
    Programmer() : Worker("程序员", "编程")
    {
    }
};
Programmer programmer;
programmer.Work();

Plan plan;
plan.Work();

Art art;
art.Work();

// 输出:
// 职位:程序员 工作内容:编程
// 职位:策划   工作内容:设计游戏
// 职位:美术   工作内容:画图建模设计UI

18.4 练习题代码

Worker.h

#pragma once
#include <iostream>
using namespace std;
class Worker
{
public:
    string type;//工种
    string content;//内容
    Worker(string type, string content) : type(type), content(content) {};
    void Work();
};

Worker.cpp

#include "Worker.h"

void Worker::Work()
{
    cout << "职位:" << type << " 工作内容:" << content << endl;
}

Art.h

#pragma once
#include "Worker.h"
class Art : public Worker
{
public:
    Art() : Worker("美术", "画图建模设计UI")
    {

    }
};

Plan.h

#pragma once
#include "Worker.h"
class Plan : public Worker
{
public:
    Plan() : Worker("策划", "设计游戏")
    {

    }
};

Programmer.h

#pragma once
#include "Worker.h"
class Programmer : public Worker
{
public:
    Programmer() : Worker("程序员", "编程")
    {

    }
};

Lesson18_练习题.cpp

#include <iostream>
#include "Programmer.h"
#include "Plan.h"
#include "Art.h"
int main()
{
    #pragma region 练习题
    /*有一个打工人基类,有工种,工作内容两个特征,一个工作方法
    程序员、策划、美术分别继承打工人
    请用继承中的构造函数这个知识点
    实例化3个对象,分别是程序员、策划、美术*/

    Programmer programmer;
    programmer.Work();

    Plan plan;
    plan.Work();

    Art art;
    art.Work();

    //职位:程序员 工作内容:编程
    //职位:策划 工作内容:设计游戏
    //职位:美术 工作内容:画图建模设计UI

    #pragma endregion

}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏