C++面向对象三大特征-----继承(详细版)

目录

继承

一、继承的基础介绍

普通版网页和继承版网页的区别

语法

二、继承方式

三种继承方式

三、继承中的对象模型

四、继承中构造和析构函数

五、继承同名成员的处理方式

访问同名成员:

作用域写法:

六、继承同名静态成员的处理方式

访问同名成员:

为什么能用类名访问静态成员?

静态成员:

静态成员函数:

总结:

七、多继承语法

语法:

八、菱形继承

概念:

菱形继承问题:

解决办法:

虚继承语法:

总结:


继承

一、继承的基础介绍

继承是面向对象三大特征之一

有些类和类之间存在特殊关系,如:

我们可以发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的个性。这个时候我们就可用继承的技术减少重复代码。 继承的基本语法 如很多网站中都有公共的头部,公共的底部,公共的左侧列表,只有中心内容不同,接下来用普通写法和继承写法来实现网页(我以CSDN的网页为例)中的内容,看一下继承存在的意义以及好处

普通版网页和继承版网页的区别

普通版网页

//普通版网页
class ZhuYe
{
public:void head(){cout << "博客  下载  学习  社区  C知道    GitCode InsCode" << endl;}void foot(){cout << "用户名 关注 收藏" << endl;}void left(){cout << "原创 周排名  总排名 访问" << endl;}
};
​
class Czhidao
{
public:void head(){cout << "博客  下载  学习  社区  C知道    GitCode InsCode" << endl;}void foot(){cout << "用户名 关注 收藏" << endl;}void context(){cout << "请输入你的问题" << endl;}void left(){cout << "原创 周排名  总排名 访问" << endl;}
​
};
​
​
class SheQu
{
public:void head(){cout << "博客  下载  学习  社区  C知道    GitCode InsCode" << endl;}void foot(){cout << "用户名 关注 收藏" << endl;}void context(){cout << "与我相关 最新发布 最新回复 最热 有活动 有问题" << endl;}void left(){cout << "原创 周排名  总排名 访问" << endl;}
​
};
​
void test01()
{ZhuYe a;a.head();a.foot();a.left();cout << "-------------------------" << endl;
​Czhidao b;b.head();b.context();b.foot();b.left();cout << "-------------------------" << endl;
​SheQu c;c.head();c.context();c.foot();c.left();
}
​
int main()
{test01();return 0;
}

其实会发现这个代码中有大量重复代码,这样子的代码是很Low的,也不符合C++是面向对象的语言的标准,而且会使得代码量加大,这个在企业开发中是一定要杜绝

继承版网页

//继承版网页
class ZhuYe
{
public:void head(){cout << "博客  下载  学习  社区  C知道    GitCode InsCode" << endl;}void foot(){cout << "用户名 关注 收藏" << endl;}void left(){cout << "原创 周排名  总排名 访问" << endl;}
};
​
class Czhidao : public ZhuYe
{
public:void context(){cout << "请输入你的问题" << endl;}
};
​
​
class SheQu : public ZhuYe
{
public:void context(){cout << "与我相关 最新发布 最新回复 最热 有活动 有问题" << endl;}
};
​
void test01()
{ZhuYe a;a.head();a.foot();a.left();cout << "-------------------------" << endl;
​Czhidao b;b.head();b.context();b.foot();b.left();cout << "-------------------------" << endl;
​SheQu c;c.head();c.context();c.foot();c.left();
}
​
int main()
{test01();return 0;
}

以上是继承版代码,可以看出来他将重复的部分给删掉了,这里用了继承这个语法,现在我来讲讲继承的语法

语法

语法:class 子类 : 继承方式 父类

子类:又称派生类

父类:又称基类

派生类中的成员包括两大部分 一类是从基类继承过来的,一类是自己增加的成员 从基类继承过来的表现其共性,而新增的成员体现了个性

二、继承方式

三种继承方式

公共继承

保护继承

**私有继承

从图可知:

父类中的私有成员,不管子类以哪种方式继承,都不可访问

就像父亲的银行卡密码,就算你是他儿子,他也不会告诉你,因为那是他的私有财产

三、继承中的对象模型

问题,从父类继承过来的成员,哪些属于子类中?

答案:

1.父类所有非静态成员属性都会被子类继承下去 2.父类中的成员属性是被编译器给隐藏了,因此是访问不到的,但是确实被继承下去了,大家可以用以下代码检测一下

class A
{
public:int m_A;
protected:int m_B;
private:int m_C;
};
​
class B : public A
{
public:int m_D;
};
​
int main()
{B test;cout << sizeof(test) << endl;return 0;
}

以上代码的答案是:16,虽然B只能访问A的m_A,m_B,加上自己的m_D,只有12个字节数,但是父类的m_C只是不可访问,不等于其不存在,因此,可以看出来子类继承了父类中所有非静态成员

四、继承中构造和析构函数

子类继承父类后,当创建子类对象,也会调用父类的构造函数

问题:父类和子类的构造和析构函数顺序谁先谁后?

大家可以通过以下代码来看看:

class A
{
public:A(){cout << "父类构造函数执行" << endl;}~A(){cout << "父类析构函数函数执行" << endl;}
​
};
​
class B : public A
{
public:B(){cout << "子类构造函数执行" << endl;}~B(){cout << "子类析构函数函数执行" << endl;}
​
};
​
int main()
{B test;return 0;
}

会发现继承中的构造和析构顺序如下: 先构造父类,再构造子类,析构的顺序与构造的顺序相反

五、继承同名成员的处理方式

问题:当子类与父类出现同名的成员,如何通过子类对象访问父类中同名的数据呢?

访问同名成员:

访问子类同名成员 直接访问即可

访问父类类同名成员 需要加作用域

作用域写法:

对象名.父类::成员名

大家可以看看以下代码来理解

class A
{
public:int m_A = 10;
};
​
class B : public A
{
public:int m_A = 20;
};
​
​
int main()
{B test;cout << test.m_A << endl;cout << test.A::m_A << endl;
​return 0;
}

如果子类中出现与父类同名成员函数;要访问就要加作用域

六、继承同名静态成员的处理方式

继承同名静态成员在子类对象上如何访问? 静态成员和非静态成员出现同名,处理方式一致

访问同名成员:

访问子类同名成员 直接访问即可

访问父类类同名成员 需要加作用域

不过,静态成员有两种方式访问

通过对象

通过类名

第一种方法与非静态成员一样的方式,我就不过多赘述,我来讲讲第二种方式

为什么能用类名访问静态成员?

因为静态成员与静态成员函数在内存中都只有一份,所以所有对象都能直接访问他,因此只需要类名就能知道它具体的值

类名访问语法(以以下代码的访问为例)

class A
{
public:static int m_A;
};
int A::m_A = 10;
​
class B : public A
{
public:static int m_A;
};
int B::m_A = 20;
​
int main()
{cout << B::m_A << endl;cout << B::A::m_A << endl;
​return 0;
}

插入静态成员知识点:

静态成员:

类型前加static

类内声明,类外初始化,一定要初始(因为静态变量放在全局区,全局区在编译阶段就分配内存)

静态成员函数:

返回类型前加static

只可访问静态变量

总结:

同名静态成员处理方式和非静态处理方式一样,只不过有两种访问方式(对象,类名)

七、多继承语法

C++中允许一个类继承多个类

语法:

class 子类 : 继承方式 父类1,继承方式 父类2, 继承方式 父类3……

多继承可能会引发父类有同名成员出现,要加作用域区分,因为容易出错,所以C++实际开发中不建议用多继承,因此不作过多介绍

八、菱形继承

概念:

两个派生类继承同一个基类 ​ 又有某个类同时继承两个派生类

以下例子虽然不符合事实动物的来源,但是有利于理解,大家就理解概念就好

菱形继承问题:

1.羊继承了动物的数据,驼同样继承了动物的数据,当羊驼使用数据时,就会产生二义性

class Animal
{
public:int m_Age;
};
​
class Sheep:public Animal
{
public:int m_Age;
};
​
class Tuo :public Animal
{
public:int m_Age;
};
​
class SheepTuo :public Sheep, public Tuo
{
public:int m_Age;
};
​
​
void test()
{SheepTuo st;st.Sheep::m_Age = 20;st.Tuo::m_Age = 10;
}
​
int main()
{test();return 0;
}

以上代码就有二义性:羊驼的年龄应该是和羊一样为20岁,还是应该和驼一样为10岁呢?

2.羊驼继承的动物的数据继承了两份,这份数据我们只需要一份就行

解决办法:

利用虚继承,解决菱形继承的问题

虚继承语法:

在继承之前加上关键字virtual变成虚继承

class Animal
{
public:int m_Age;
};
​
class Sheep:virtual public Animal
{
public:int m_Age;
};
​
class Tuo :virtual public Animal
{
public:int m_Age;
};
​
class SheepTuo :public Sheep, public Tuo
{
public:int m_Age;
};
​
​
void test()
{SheepTuo st;st.Sheep::m_Age = 20;st.Tuo::m_Age = 10;
}
​
int main()
{test();return 0;
}

这时你

cout << st.m_Age << endl;
cout << st.Sheep::m_Age << endl;
cout << st.Tuo::m_Age << endl;

都是等于10,因为三者在实际上时共用了一个数据,这里涉及了虚拟基类指针和虚拟基类表,这里涉及开发命令页的操作来展现,大家感兴趣的可以自行查找相关资料

总结:

菱形继承带来的主要问题是:子类继承两份相同的数据导致资源浪费以及毫无意义 可以用虚拟继承方式解决

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞桨AI应用@riscv OpenKylin

在riscv编译安装飞桨PaddlePaddle参见&#xff1a; 算能RISC-V通用云编译飞桨paddlepaddleopenKylin留档_在riscv下进行paddlelite源码编译-CSDN博客 安装好飞桨&#xff0c;就可以用飞桨进行推理了。刚开始计划用ONNX推理&#xff0c;但是在算能云没有装上&#xff0c;所以最…

智慧城市与数字孪生:科技融合助力城市可持续发展

随着信息技术的迅猛发展&#xff0c;智慧城市和数字孪生作为现代城市发展的重要理念和技术手段&#xff0c;正日益受到广泛关注。智慧城市通过集成应用先进的信息通信技术&#xff0c;实现城市管理、服务、运行的智能化&#xff0c;而数字孪生则是利用数字化手段对物理城市进行…

安卓手机系统跳过app启动广告软件

跳过广告关于此应用声明&#xff1a; 应用利用了安卓系统的辅助功能API&#xff0c;可以读取您手机屏幕上显示的所有内容&#xff0c;并且可以以您的名义进行屏幕点击等操作。* 轻量无广告&#xff0c;不联网&#xff0c;也不需要任何权限&#xff1b;* 请务必在系统设置中开启…

【LabVIEW FPGA入门】FPGA 存储器(Memory)

可以使用内存项将数据存储在FPGA块内存中。内存项以2kb为倍数引用FPGA目标上的块内存。每个内存项引用一个单独的地址或地址块&#xff0c;您可以使用内存项访问FPGA上的所有可用内存。如果需要随机访问存储的数据&#xff0c;请使用内存项。 内存项不消耗FPGA上的逻辑资源&…

鲁棒的基于表面势的GaN HEMT集成电路紧凑模型

来源&#xff1a;Robust Surface-Potential-Based Compact Model forGaN HEMT IC Design&#xff08;TED 13年&#xff09; 摘要 我们提出了一种精确且稳健的基于表面势的紧凑模型&#xff0c;用于模拟采用氮化镓高电子迁移率晶体管&#xff08;GaN HEMT&#xff09;设计的电…

解决前端跨域问题

前端跨域问题 该问题是由于前端的服务路径或端口和后台的不一致所导致的 Springboot跨域设置 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; …

[linux][调度] 内核抢占入门 —— 线程调度次数与 CONFIG_PREEMPTION

在工作中&#xff0c;如果你正在做开发的工作&#xff0c;正在在写代码&#xff0c;这个时候测试同事在测试过程中测出了问题&#xff0c;需要你来定位解决&#xff0c;那么你就应该先暂停写代码的工作&#xff0c;转而来定位解决测试的问题&#xff1b;如果你正在定位测试的问…

区块链技术下的新篇章:DAPP与消费增值的深度融合

随着区块链技术的持续演进&#xff0c;去中心化应用&#xff08;DAPP&#xff09;正逐渐受到人们的瞩目。DAPP&#xff0c;这种在分布式网络上运行的应用&#xff0c;以其去中心化、安全可靠、透明公开的特性&#xff0c;为用户提供了更为便捷和安全的消费体验。近年来&#xf…

生成式AI有哪些优越性

生成式人工智能&#xff08;AI&#xff09;近年来取得了显著的进展&#xff0c;其优势主要体现在以下几个方面&#xff1a; 创造性和创新能力&#xff1a;生成式AI能够产生全新的内容&#xff0c;包括文本、图像、音乐等&#xff0c;这些内容在某种程度上是创新的。它可以帮助艺…

springboot+vue考试管理系统

基于springboot和vue的考试管理系统 001 springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的在线考试管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

Centos7部署单节点MongoDB(V4.2.25)

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

Swagger3/2+Spring boot 使用小结

一&#xff1a;前言 Swagger 是一个 RESTful API 的开源框架&#xff0c;它的主要目的是帮助开发者设计、构建、文档化和测试 Web API。Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式&#xff0c;以提高 API 的可读性、可靠性和易用性&#xff0c;同时降低 A…

ETCD跨城容灾与异地多活网络故障的相关表现分析

ETCD跨城容灾与异地多活网络故障的相关表现分析 1. 网络架构2. 单个网络中断-跟leader区中断2.1. 网络中断2.2. 网络恢复 3. 单个网络中断-跟非leader区中断4. 两个网络中断-leader区中断5. 两个网络中断-非leader区中断6. 两个网络中断-非leader区中断7. 总结8. 参考文档 etcd…

CRC计算流程详解和FPGA实现

一、概念 CRC校验&#xff0c;中文翻译过来是&#xff1a;循环冗余校验&#xff0c;英文全称是&#xff1a;Cyclic Redundancy Check。是一种通过对数据产生固定位数的校验码&#xff0c;以检验数据是否存在错误的技术。 其主要特点是检错能力强、开销小&#xff0c;易于电路实…

记录开发STM32遇到的卡死问题-串口

背景&#xff1a;以STM32作为主控&#xff0c;广州大彩显示屏显示&#xff0c;主控实时采集数据&#xff0c;串口波特率115200.设置收发频率为50Hz&#xff0c;即单片机每秒发送50帧数据&#xff0c;每秒接收50帧数据&#xff0c;每帧数据大概14字节。 问题&#xff1a;系统长…

智能优化算法 | Matlab实现牛顿-拉夫逊优化算法Newton-Raphson-based optimize(内含完整源码)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 智能优化算法 | Matlab实现牛顿-拉夫逊优化算法Newton-Raphson-based optimize(内含完整源码) 源码设计 % ------------------------------------------------------------------------------------------------…

鸿蒙一次开发,多端部署(十五)常见问题

如何查询设备类型 设备类型分为default&#xff08;默认设备&#xff09;、tablet、tv、wearable、2in1等&#xff0c;有多种查询设备类型的方式。 通过命令行的方式查询设备类型。 通过命令行查询指定系统参数&#xff08;const.product.devicetype&#xff09;进而确定设备…

软件设计师笔记

计算机 运算器组成&#xff1a;算术逻辑单元(ALU)、累加寄存器(AC)、数据缓冲寄存器(DR)、状态条件寄存器()等组成。 控制器组成&#xff1a;指令寄存器(IR)、程序计数器(PC)、地址寄存器(AR)、指令译码器(ID)。 最小数据单位&#xff1a;bit 最小存储单位: byte n进制 转 1…

力扣爆刷第103天之CodeTop100五连刷1-5

力扣爆刷第103天之CodeTop100五连刷1-5 文章目录 力扣爆刷第103天之CodeTop100五连刷1-5一、3. 无重复字符的最长子串二、206. 反转链表三、146. LRU 缓存四、215. 数组中的第K个最大元素五、25. K 个一组翻转链表 一、3. 无重复字符的最长子串 题目链接&#xff1a;https://l…

使用Intellij idea编写Spark应用程序(Scala+Maven)

使用Intellij idea编写Spark应用程序(ScalaMaven) 对Scala代码进行打包编译时&#xff0c;可以采用Maven&#xff0c;也可以采用sbt&#xff0c;相对而言&#xff0c;业界更多使用sbt。这里介绍IntelliJ IDEA和Maven的组合使用方法。IntelliJ IDEA和SBT的组合使用方法&#xf…