C++基础知识(六:继承)

首先我们应该知道C++的三大特性就是封装、继承和多态。

此篇文章将详细的讲解继承的作用和使用方法。

  • 继承

一个类,继承另一个已有的类,创建的过程

父类(基类)派生出子类(派生类)的过程

继承提高了代码的复用性

【1】继承的格式

class 类名:父类名
{};

【2】继承的权限

class 类名:继承的权限 父类名
{};如果不写继承方式,默认是私有继承
父类中的权限      public|private|protected  public|private|protected   public|private|protected              
继承方式                 public                    private                   protected
子类中的权限      public|不能访问|protected  private|不能访问|private    protected|不能访问|protected

【3】继承时类中的特殊成员函数

特殊的成员函数不会被继承

构造函数:

  • 需要在子类中显性调用父类的构造函数(初始化列表中)(透传构造)
  • 透传构造
  • 继承构造
  • 委托构造

需要在子类中显性调用父类构造函数的场合:

父类中只有有参构造  ----->子类在创建类对象时,必须手动调用父类的构造函数

#include <iostream>using namespace std;class Father
{
public:int age;char c;Father(int a,char c):age(a),c(c){cout << "Father有参" << endl;}
};class Child:public Father    //----->私有继承
{int high;
public:void show(){
        cout << c << endl;}
};int main()
{//Child c1;  //error,因为父类只有有参构造,而子类中没有提供能够调用父类有参构造的构造函数,不能成功创建父类的空间//Father f1;
    c1.age;
    cout << sizeof (Father) << endl;
    cout << sizeof (Child) << endl;return 0;
}

i)透传构造

在子类构造函数的初始化列表中,显性调用父类的构造函数

ii)继承构造

C++支持

不用在子类中再写一遍父类的构造函数

使用:using Father::Father; ----->在子类中使用父类的构造函数

直接使用继承构造的方式,不能对子类成员初始化

继承构造本质上并不是把父类中的构造函数继承给子类,编译器自动根据父类中构造函数的格式,提供出派生的构造函数(个数和参数都和父类中的构造函数一致),主要还是通过透传构造创建父类的空间

#include <iostream>
using namespace std;class Father
{
public:int age;char c;
//    Father(){cout << "Father无参" << endl;}Father(int a,char c):age(a),c(c){cout << "Father有参两个参数" << endl;}Father(char c):c(c){cout << "Father有参一个参数的" << endl;}Father(Father &other):age(other.age),c(other.c){cout << "Father拷贝" << endl;}
};class Child:public Father    //----->私有继承
{
private:int high;//父类中的public成员age,通过公有继承,仍然是publicusing Father::age;   //把父类中公有继承下来的age成员,在子类中改成私有权限
public:void show(){
        cout << c << endl;}//子类的无参构造,但是显性调用父类的有参构造还给了默认值//透传构造
//    Child():Father(12,'a'){cout << "Child无参构造" << endl;}
//    Child(int a,char c,int h):Father(a,c),high(h)
//    {cout << "Child有参构造" << endl;}//父类中的所有构造函数,都被继承到了子类中using Father::Father;   //更高效一些
};int main()
{
    Child c1(10);
    Child c2(20,'z');
    Child c3 = c2;//Father f1;//c1.age;
    cout << sizeof (Father) << endl;
    cout << sizeof (Child) << endl;return 0;
}

iii)委托构造

一个类的情况,并不直接通过无参构造实例化对象,而是无参构造委托了有参构造,实例化对象

继承时的情况

    Child():Child(10){cout << "Child无参构造" << endl;}   //Child c1
    Child(int a):Father(12,'a'),high(a)
    {cout << "Child有参构造一个参数" << endl;}

iv)拷贝构造

需要在初始化列表中显性调用父类的拷贝构造,传other对象到父类的拷贝构造中

Father(Father &other):age(other.age),c(other.c){cout << "Father的拷贝构造" << endl;}
Child(Child &other):Father(other),high(other.high){}

【4】继承时构造和析构的时机

继承关系,可以理解为包含关系

子类在继承父类时,会把父类中的成员保留一份,再来创建子类自己的成员

父类先构造,子类后构造

子类先析构,父类后析构

#include <iostream>using namespace std;
class F
{int *p;
public:F():p(new int){cout << "F无参构造" << endl;}~F(){delete p;
        cout << "F析构函数" << endl;}
};
class C:public F
{int *p;
public:C():p(new int){cout << "C无参构造" << endl;}~C(){delete p;
        cout << "C析构函数" << endl;}
};int main()
{
    C *p1 = new C;delete p1;   //空间释放时,会自动调用析构函数,无需手动调用
    p1 = nullptr;return 0;
}

【5】父子类中存在同名成员问题

访问时不会发生冲突,默认访问子类的

#include <iostream>
using namespace std;
class F
{
public:int *p;F():p(new int){cout << "F无参构造" << endl;}~F(){delete p;
        cout << "F析构函数" << endl;}
};
class C:public F
{
public:int *p;C():p(new int){cout << "C无参构造" << endl;}~C(){delete p;
        cout << "C析构函数" << endl;}
};int main()
{
    C *p1 = new C;*(p1->p) = 90;
    cout << *(p1->p) << endl;   //子类成员和父类成员同名,默认优先访问子类成员
    cout << *(p1->F::p) << endl;  //通过域限定符访问父类的成员delete p1;   //空间释放时,会自动调用析构函数,无需手动调用
    p1 = nullptr;return 0;
}
  • 多重继承

一个子类,继承自多个基类

【1】格式

class 类名:继承权限 父类名,继承权限 父类名····
{}

【2】当多个父类中包含同名成员

多个父类中包含同名成员,通过域限定符访问指定的父类中成员

#include <iostream>using namespace std;class Room
{
public:void clean(){
        cout << "打扫房间" << endl;}
};
class BedRoom
{
public:void play(){
        cout << "可以玩游戏" << endl;}void clean(){
        cout << "打扫卧室" << endl;}
};//Home类公共继承字Room和BedRoom类
class Home:public Room,public BedRoom
{
};int main()
{
    Home h1;
    h1.play();
    h1.Room::clean();
    h1.BedRoom::clean();return 0;
}
  • 菱形继承(钻石继承)

【1】格式

     A                ----->公共基类/   \
  B     C             ------>中间子类
   \   /
     D                ------>汇集子类

汇集子类中,会包含两份公共基类中的内容

【2】菱形继承存在的问题

  1. 会发生二义性的问题(同一个变量或者函数,可以通过两种方法访问)
  2. 如果公共基类,过大,会造成汇集子类中的代码膨胀/冗余
#include <iostream>using namespace std;
class A
{
public:int a;//A(int a):a(a){cout << "A" << endl;}
};class B:public A
{
public:int c;//B(int a,int c):A(a),c(c){cout << "B" << endl;}
};class C:public A
{
public://C(int a):A(a){cout << "C" << endl;}
};class D:public C,public B
{
public://D(int a,int c):B(a,c),C(a),A(a){cout << "D" << endl;}
};int main()
{
    D d1;
    d1.B::= 90;   //二义性,还可以直接通过中间子类访问,直接访问B中的a成员//cout << d1.C::A::a << endl;  //会发生二义性,因为访问A,但是有两条路径都访问到Areturn 0;
}

【3】虚继承(virtual)

虚继承指对公共基类的虚继承。

主要用于解决菱形继承问题,

采用虚继承后,公共基类中的内容,只会在汇集子类中存在一份,在汇集子类中,可以通过任意一条路径访问到公共基类中的成员

#include <iostream>using namespace std;
class A
{
public:int a;
};class B:virtual public A
{
public:int c;
};class C:virtual public A
{};class D:public B,public C
{};int main()
{
    D d1;
    d1.B::A::= 90;
    cout << d1.C::A::<< endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2805697.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

机器视觉选型:如何选择一个合适光源控制器

在机器视觉系统中&#xff0c;选择合适的光源及其控制器对于确保高质量图像捕获和处理至关重要。本文会提供一些建议&#xff0c;以便于引导您了解如何基于应用需求选择最合适的光源和光源控制器。 1. 理解光源的功率需求 不同类型的光源具有不同的功率需求&#xff0c;这直接…

汽水分离器——矿用分离过滤装置

去找一个奋发向上能带动你的人&#xff0c;去找一个像太阳一样的人&#xff0c;帮你晒晒全部不值一提的迷茫! 一、结构&#xff1a; 气水分离器又称气水分离过滤器&#xff0c;主要由&#xff1a;进口、筒体、滤芯连接件、滤芯、密封圈、阀门连接件、出气管、排水口、压力表等…

多人协作记账账本小程序开源版开发

多人协作记账账本小程序开源版开发 支持多人协作的记账本小程序&#xff0c;可用于家庭&#xff0c;团队&#xff0c;组织以及个人的日常收支情况记录&#xff0c;支持周月年度统计 便捷记账 便捷的记账方式&#xff0c;支持多种记账类型&#xff0c;快捷切换账本等 多账本 支…

JavaScript的内存管理与垃圾回收

前言 JavaScript提供了高效的内存管理机制&#xff0c;它的垃圾回收功能是自动的。在我们创建新对象、函数、原始类型和变量时&#xff0c;所有这些编程元素都会占用内存。那么JavaScript是如何管理这些元素并在它们不再使用时清理它们的呢&#xff1f; 在本节中&#xff0c;…

汽车大灯尾灯破裂修复用什么胶?

汽车大灯尾灯破裂可以使用硅酮玻璃胶或者环氧树脂胶进行修复。 硅酮玻璃胶的优点主要包括&#xff1a; 粘接力强&#xff1a;硅酮玻璃胶具有很强的粘接力&#xff0c;可以有效地将裂缝两侧的材料紧密粘合在一起。拉伸强度大&#xff1a;硅酮玻璃胶固化后形成的固体具有较高的…

VM-UNet: Vision Mamba UNet for Medical Image Segmentation

VM-UNet: 基于纯 Mamba 架构的医学图像分割模型 论文地址&#xff1a;https://arxiv.org/abs/2402.02491 项目地址&#xff1a;https://github.com/JCruan519/VM-UNet Abstract 在医学图像分割领域&#xff0c;基于CNN和基于Transformer的模型都得到了广泛的探索。然而&#…

基于Android的记单词App系统的研究与实现,附附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Mamba 作者谈 LLM 未来架构

文章目录 前言 1、为什么注意力机制有效&#xff1f; 2、注意力计算量呈平方级增长 3、Striped Hyena 是个什么模型&#xff1f; 4、什么是 Mamba? 5、Mamba 硬件优化 6、2024年架构预测 7、对 AI 更多的预测 本片文章来自【机器之心】对Mamba作者进行采访所进行的编译整理。 …

springboot+vue项目部署配置开机自启动

1.前端部属 下载nginx解压&#xff0c;在nginx\conf下找到nginx.conf 添加如下代码 server {listen 8081;server_name localhost;charset utf-8;location / {root F:/1ceshi/dist; #前端打包路径try_files $uri $uri/ /index.html;index index.html index.htm;}l…

【动态规划】【前缀和】【推荐】2463. 最小移动总距离

作者推荐 【广度优先搜索】【网格】【割点】【 推荐】1263. 推箱子 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 2463. 最小移动总距离 X 轴上有一些机器人和工厂。给你一个整数数组 robot &#xff0c…

2.5G/5G/10G高速率网络变压器(网络隔离变压器)产品介绍(1)

Hqst华轩盛(石门盈盛)电子导读&#xff1a;高速率/2.5G 的带POE插件&#xff08;DIP&#xff09;款千兆双口网络变压器2G54801DP特点 一 ﹑2.5G高速率网络变压器&#xff08;网络隔离变压器&#xff09;&#xff1a;2G54801DP外观与尺寸 2G54801DP这颗产品尺寸为&#xff1a;长…

备战蓝桥杯————双指针技巧巧解数组2

利用双指针技巧来解决七道与数组相关的题目。 两数之和 II - 输入有序数组&#xff1a; 给定一个按升序排列的数组&#xff0c;找到两个数使它们的和等于目标值。可以使用双指针技巧&#xff0c;在数组两端设置左右指针&#xff0c;根据两数之和与目标值的大小关系移动指针。 …

测试计划、测试方案、测试策略、测试用例的区别

一 测试计划 测试计划是指描述了要进行的测试活动的范围、方法、资源和进度的文档。它主要包括测试项、被测特性、各阶段的测试任务、时间进度安排&#xff0c;谁执行任务和风险控制等&#xff0c;可以包括测试策略。 二 测试方案 测试方案是指描述需要测试的特性、测试的方…

MT8791迅鲲900T联发科5G安卓核心板规格参数_MTK平台方案定制

MT8791安卓核心板是一款搭载了旗舰级配置的中端手机芯片。该核心板采用了八核CPU架构设计&#xff0c;但是升级了旗舰级的Arm Cortex-A78核心&#xff0c;两个大核主频最高可达2.4GHz。配备了Arm Mali-G68 GPU&#xff0c;通过Mali-G88的先进技术&#xff0c;图形处理性能大幅提…

如何查看电脑使用记录?保障个人隐私和安全

查看电脑使用记录是了解电脑活动的一种重要方式&#xff0c;可以帮助用户追踪应用程序的使用情况、登录和关机时间、文件的访问记录等。在本文中&#xff0c;我们将介绍如何查看电脑使用记录的三个方法&#xff0c;以分步骤详细说明如何查看电脑使用记录&#xff0c;帮助用户更…

Jenkins中Publish Over SSH插件使用(1)

SSH插件 前言Publish Over SSH插件是jenkins里面必不可少的插件之一&#xff0c;主要的功能有两个把jenkins服务器上的文件&#xff0c;传输到远程nginx&#xff0c; 远程执行shell命令和脚本。 1. SSH插件下载与配置 1.1 下载Publish over SSH插件 系统管理—》管理插件 …

数据存储-文件存储

一、CSV文件存储 csv是python的标准库 import csvheader [班级, 姓名, 性别, 手机号, QQ]# 二维数组 rows [[学习一班, 大娃, 男, a130111111122, 987456123],[学习二班, 二娃, 女, a130111111123, 987456155],[学习三班, 三娃, 男, a130111111124, 987456123], ]f open(r…

springboot邮箱注册

1.准备工作 操作之前准备两个邮箱 我准备了网易邮箱和QQ邮箱&#xff0c;网易邮箱用来发送验证码&#xff0c;QQ邮箱用来做注册&#xff08;希望大家和我一样&#xff0c;不然可能会出错 &#xff09; 发送验证码的邮箱需要开启一些设置&#xff0c;否则不…

小程序画布(二维地图线)

首先开始是想用小程序兼容openlayers的&#xff0c;但是了解到用不了&#xff0c;那就用画布来解决 实际效果如下 wxml中代码 <canvas id"trackDesignCanvas" //指定 id 的 Canvas 组件class"orbit-canvas-main" type"2d" …

C++之deque

一、vector与list的优缺点 vector的优点&#xff1a;下标的随机访问&#xff0c;尾插&#xff0c;尾删效率高。CPU高速缓存命中率高vector的缺点&#xff1a;扩容(效率&#xff0c;空间浪费)&#xff0c;不适合头插头删。 连续的物理空间为他带来了优点也带来了缺点&#xff0c…