C++类和对象特性之继承详解

本文详细探讨了C++中的继承概念,包括public、protected和private三种方式,讲解了构造函数和析构函数的执行顺序,以及如何处理子类与父类同名成员。还介绍了多继承和菱形继承问题,以及虚继承的解决方案。

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

一、继承的含义

由父类(基类)派生出子类(派生类),子类会选择性地继承父类的特性。借此,我们可以减少代码的冗余 提高代码的重用性。

二、继承的语法

 class 子类: 继承方式 父类名{
 //子类新增的数据成员和成员函数
 };

三、三种继承方式

在这里插入图片描述

  1. 继承方式为pubilc

此时子类继承了父类中的public和protected属性,其中两种属性在子类中的访问权限与在父类中相同,但是父类中的private属性子类虽然被继承,但是被隐藏无法访问。

class teacher {

public:
    string name;

protected:
    int age;
   
private:
    int score;

};

class student:  public teacher {
public:

    void look()
    {
        name="Tom";
        age=18;
        score=;
    }

  
};

在这里插入图片描述

  1. 继承方式为protected
    此时子类继承了父类中的public和protected属性,其中两种属性在子类中的访问权限都为protected,但是父类中的private属性子类虽然被继承,但是被隐藏无法访问。
class teacher {

public:
    string name;

protected:
    int age;
   
private:
    int score;

};

class student:  protected teacher {
public:

    void look()
    {
        name="Tom";
        age=18;
        score=100;
    }

  
};


void test1()
{
    student stu;
    stu.name="TOM";
    stu.age=18;
    stu.score=100;
    
}

在这里插入图片描述

  1. 继承方式为private

此时子类继承了父类中的public和protected属性,其中两种属性在子类中的访问权限都为private,但是父类中的private属性子类虽然被继承,但是被隐藏无法访问。通过给student类一个子类,发现由于student类内的属性都是private所以子类无法访问。

class teacher {

public:
    string name;

protected:
    int age;
   
private:
    int score;

};

class student:  private teacher {
public:

    void look()
    {
        name="Tom";
        age=18;
        score=100;
    }

  
};

class son: public student {
    public:
        void look()
        {
            name="Tom";
            age=10;
            score=10;
        }
};

在这里插入图片描述

四、构造函数和析构函数的顺序

  1. 创建子类对象的同时也会创建一个父类对象
  2. 构造函数的执行是父类先于子类,析构函数的执行是子类先于父类
#include <iostream>
#include <string>

using namespace std;


class teacher {

public:
   teacher()
   {
       cout<<"父类的构造函数"<<endl;
   }

   ~teacher()
   {
       cout<<"父类的析构函数"<<endl;
   }

};

class student:  private teacher {
public:

    student()
    {
        cout<<"子类的构造函数"<<endl;
    }

    ~student()
    {
        cout<<"子类的构造函数"<<endl;
    }

  
};




void test1()
{
    student stu;
}


int main()
{
    test1();            
   
    system("pause");    
}

在这里插入图片描述

  1. 如果调用了其他类作为成员:
    在这里插入图片描述

五、解决子类和父类中的同名成员

  1. 当子类和父类中有同名的成员变量时,直接调用子类的该成员变量,访问的是子类的而不是父类的。
  2. 可以通过加作用域来判断访问的是否是继承于父类的属性
    在这里插入图片描述
  3. 如果子类中的成员函数和父类的相同,则会隐藏父类的所有该同名函数,但是我们可以通过作用域来访问父类的成员函数
    在这里插入图片描述
  4. 同名的静态函数、静态成员变量处理方式和上面相同

六、多继承

  1. 多继承的语法:
class 子类: 继承方式1 父类名1,继承方式2 父类名2,继承方式3 父类名3,....
 {

 };
  1. 实际开发中不支持使用多继承,因为继承多个父类容易出现同名成员的冲突,这时需要使用加上作用域的方法来解决。

七、菱形继承

  1. 菱形继承的概念:

当一个类继承了多个父类,而那些父类又有他们共同的父类,那么这些父类中就会有一些相同的属性。这样的话第一个类(所有类的子类)就会多次继承同一种数据,这样会造成资源的浪费,而且容易造成二义性。

  1. 解决方法
    ①对于二义性的解决方法在前面都有介绍,就是给成员属性加上作用域。但是这样还是会造成资源浪费。
    ②为了同时解决二义性和资源浪费的问题,我们可以采用虚继承。

八、虚继承

  1. 虚继承的语法
class 子类:virtual public 父类
 {
 };
  1. 虚继承的本质
    利用虚基类指针vbptr指向虚基类表,而虚基类表vbtable保存了当前的虚指针相对于虚基类的首地址的偏移量。通过偏移量找到父类中的属性,这样就可以只用一份数据的资源了。
    在这里插入图片描述
    在这里插入图片描述
  2. 虚继承在实际开发中也不支持使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值