【C++】面向对象 继承与派生 知识点总结

本文总结了C++中面向对象的继承与派生知识点,包括基本概念、派生类成员的访问属性以及派生类的构造函数和析构函数。通过实例解释了不同继承方式下成员的访问权限,以及构造函数和析构函数的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基本概念

1、概念

继承和派生是一个东西,在定义一个新的类B时,若该类与已有的类A相似(即B拥有A的全部特点),则可把A作为基类(也称父类),B作为基类的一个派生类(也称子类)。派生类拥有基类全部的成员函数和成员变量,但不能访问基类中的private成员。

2、派生类写法
class 派生类名:基类名
{
    
};

举个例子:

class people
{
private:
    string name;
    int age;
public:
    void get()
    {
        cin>>name>>age;
    }
    void display()
    {
        cout<<"name: "<<name<<endl;
        cout<<"age: "<<age<<endl;
    }
};
class student: public people
{
private:
    int score;//派生类可以对基类进行扩充
public:
    void get()
    {
        people::get();
        cin>>score;
    }
    void display()
    {
        people::display();// 调用people类(基类)里面的display成员函数
        cout<<"score: "<<score<<endl;
    }//覆盖(派生类可以对基类进行修改)
};
int main()
{
    student a1;
    a1.get();//访问派生类student里面的get函数
    a1.display();//访问派生类student里面的display函数
    return 0;
}

运行结果为:
在这里插入图片描述

3、需要继承与派生的例子

在这里插入图片描述

4、注意事项

  1. 继承方式决定了派生类对基类成员的访问权限,默认为私有继承private,最常用的是共有继承public,还有一种是保护继承protected

  2. 派生类可以对基类进行扩充和修改(可参考派生类写法中的例子)。在派生类中,可以扩充新的成员变量和成员函数。

  3. 在派生类中声明一个和基类成员同名的成员,来“覆盖”接收的基类成员。如果想覆盖成员函数,其函数名和参数表必须相同,否则成为重载。

  4. 派生类也可被其他类继承,则这个派生类同时也是基类。

  5. 构造函数和析构函数是不能继承的,要重新定义。

  6. 派生类一经定义,即可不依赖基类,独立使用。

二、派生类成员的访问属性

1、不同的继承方式下,基类成员在派生类中的访问方式如下:(大多数时候使用公有继承

  • 公有继承:
    基类的公有成员和保护成员在派生类中保持原有的访问属性;其私有成员仍为基类私有,派生类新增成员不可访问它。
    用如下示意图来说明公有继承的访问属性:
    在这里插入图片描述
  • 私有继承:
    基类的公用成员和保护成员在派生类中成为私有成员,其私有成员仍为基类私有,派生类新增成员不可访问它。
  • 保护继承:
    基类的公用成员和保护成员在派生类中成为保护成员,其私有成员仍为基类私有,派生类新增成员不可访问它。
    特点:
    对于派生类的成员而言,保护成员就像公有成员;但对于其他函数,保护成员是私有成员。
    总结:
    在这里插入图片描述

三、派生类的构造函数和析构函数

1、简单派生类的构造函数
  • 即指派生类只有基类,不包含基类的对象
    简单派生类的构造函数的一般形式:

派生类名(总参数表) :基类名(参数表)
{对派生类中新增数据成员初始化语句}

  1. 只有一个基类
    PL:
class people
{
private:
    string name;
    int age;
public:
    people(string n,int a):name(n),age(a){}
};
class student: public people
{
private:
    int score;
public:
    student(string n,int a,int s):people(n,a),score(s){}
};
  1. 具有多个基类(多重继承)

派生类名(总参数表列) :基类1构造函数(参数表),基类2构造函数(参数表),…
{对派生类中新增数据成员初始化语句}

PL:

class people//基类1
{
private:
    string name;
    int age;
public:
    people(string n,int a):name(n),age(a){}
};
class school//基类2
{
private:
    string schoolname;
public:
    school(string sn):schoolname(sn){}
};
class student: public people,public school//多重派生
{
private:
    int score;
public:
    student(string n,int a,string sn,int s):people(n,a),school(sn),score(s){}
};
2、包含类对象的派生类的构造函数

构造函数形式:
派生类名(总参数表):基类名(参数表),对象名(参数表)
{派生类中新增数据数据成员初始化语句}

PL:

#include <iostream>
using namespace std;
class people
{
private:
    string name;
    int age;
public:
    people(string n,int a):name(n),age(a){}
    void display()
    {
        cout<<"name: "<<name<<endl;
        cout<<"age: "<<age<<endl;
    }
};
class student: public people
{
private:
    int score;//派生类对基类进行扩充
    people c1,c2;//people的类对象
public:
    student(string n,int a,string n1,int a1,string n2,int a2,int s):people(n,a),c1(n1,a1),c2(n2,a2),score(s){}//初始化
    void display_all()
    {
        people::display();//因为派生类无法访问基类的私有数据成员
                          //所以调用people类(基类)里面的display成员函数进行输出
        c1.display();
        c2.display();
        cout<<"score: "<<score<<endl;
    }//覆盖(派生类可以对基类进行修改)
};
int main()
{
    student a1("zhangsan",13,"lisi",14,"wangwu",15,100);
    a1.display_all();
    return 0;
}

运行结果:
在这里插入图片描述

3、多层派生时的构造函数

多层派生时,只须写出其直接基类的构造函数即可

PL:

#include <iostream>
using namespace std;
class people
{
private:
    string name;
    int age;
public:
    people(string n,int a):name(n),age(a){}
    void display()
    {
        cout<<"name: "<<name<<endl;
        cout<<"age: "<<age<<endl;
    }
};
class student1: public people
{
private:
    int score;//派生类对基类进行扩充
public:
    student1(string n,int a,int s):people(n,a),score(s){}//初始化
    void display_s1()
    {
        people::display();//因为派生类无法访问基类的私有数据成员
                          //所以调用people类(基类)里面的display成员函数进行输出
        cout<<"score: "<<score<<endl;
    }//覆盖(派生类可以对基类进行修改)
};
class student2: public student1
{
private:
    string schoolname;//派生类对基类进行扩充
public:
    student2(string n,int a,int s,string sn):student1(n,a,s),schoolname(sn){}//初始化
    void display_s2()
    {
        student1::display_s1();
        cout<<"schoolname: "<<schoolname<<endl;
    }//覆盖(派生类可以对基类进行修改)
};
int main()
{
    student2 a1("zhangsan",13,100,"zs");
    a1.display_s2();
    return 0;
}

运行结果:
在这里插入图片描述
上述程序中,基类people构造 函数为:
         people(string n,int a):name(n),age(a){}
一级派生类student1构造函数为:
         student1(string n,int a,int s):people(n,a),score(s){}
二级派生类student2构造函数为:
         student2(string n,int a,int s,string sn):student1(n,a,s),schoolname(sn){}

即每级构造函数,只须列出其上一级的构造函数。

4、派生类构造函数和析构函数的执行顺序
  1. 构造函数执行顺序:
         先执行基类的构造函数,初始化基类数据成员。
         再执行成员对象类的构造函数,初始化成员对象类的数据成员。
         最后执行派生类自身的构造函数,初始化自己新增数据成员。

  2. 析构函数执行顺序:
         先执行派生类自己的析构函数
         再依次执行各成员对象类的析构函数
         最后执行基类的析构函数
    即与构造函数调用顺序相反

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值