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.mzph.cn/news/766920.shtml

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

相关文章

Python None 值

Python None 值 References 在 Python 中有一个值称为 None&#xff0c;它表示没有值。None 是 NoneType 数据类型的唯一值。就像布尔值 True 和 False 一样&#xff0c;None 必须大写首字母 N。 如果你希望变量中存储的东西不会与一个真正的值混淆&#xff0c;这个没有值的值…

Qt播放音乐代码示例

主界面 点击play按钮播放或暂停音乐&#xff0c;拖动进度条&#xff0c;音乐对应播放。 QWidget window;QPushButton* playButton new QPushButton("Play");// Qt 播放音乐// 创建 QMediaPlayer 对象QMediaPlayer* player new QMediaPlayer;// 指定音频文件的路径…

MySQL B+树索引 和 Redis 中跳表索引的区别

一、MySQL B树索引 和 Redis 中跳表索引 在 MySQL 中常用的索引是 B树索引&#xff0c;而 Redis 中&#xff0c;例如 zset 使用的的是跳表索引&#xff0c;两者有什么区别呢&#xff0c;MySQL 为什么不使用 跳表 呢&#xff1f;或者说 Redis 中为什么不使用 B树 呢&#xff1f…

AT25HP256/512

关于AT25HP256/512系列串行EEPROM&#xff08;电气可擦可编程只读存储器&#xff09;的数据手册&#xff0c;由Atmel公司发布。这些存储器通过串行外设接口&#xff08;SPI&#xff09;与微控制器等设备通信&#xff0c;并提供高可靠性的数据存储解决方案。以下是文档内容的翻译…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…

golang 对接第三方接口 RSA 做签(加密) 验签(解密)

一、过程 1.调用第三方接口前&#xff0c;一般需要按规则将参数按key1value1&key2value2 阿斯克码排序,sign参数不参与加密 2.将排序并连接好的参数字符串通过我方的私钥证书&#xff08;.pem&#xff09;进行加密得到加密串&#xff0c;当然加密得到的是 []byte 字节流&…

变量赋值篇

文章目录 变量赋值增量赋值多重赋值多元赋值合法的标识符 变量赋值 在Python中&#xff0c;变量赋值是一个简单的操作&#xff0c;你可以使用等号&#xff08;&#xff09;来将一个值赋给一个变量。以下是一些基本的变量赋值示例&#xff1a; # 整数赋值 x 10# 浮点数赋值 y…

Excel文件导入导出,SpringBoot整合EasyExcel批量导入导出,采用的JDBC+EasyExcel(附带整个Demo)

目录 0.为什么mybatis的foreach比JDBC的addBatch慢 1.引入依赖 2.Controller层 3.Service层 4.Utils工具类 5.自定义监听器 6.实体类 7Mapper层 不用Mybatis的原因就是因为在大量数据插入的时候jdbc性能比mybatis好1. 首先分批读取Excel中的数据 这一点EasyExcel有自己…

看完就等于拿捏浮点数在内存中的储存了

诸君又该学习了&#xff0c;今天我们继续来一睹浮点数的奥妙真容。 经过前面文章对整形提升相关的解释&#xff0c;我们都对整形和字符在内存空间上的储存已经有了大概的认知&#xff0c;那么现在我们就来好好讲讲浮点数在内存中的储存规则。 目录 浮点数与整形储存的不同 …

41-Vue-webpack基础

webpack基础 前言什么是webpackwebpack的基本使用指定webpack的entry和output 前言 本篇开始来学习下webpack的使用 什么是webpack webpack: 是前端项目工程化的具体解决方案。 主要功能&#xff1a;它提供了友好的前端模块化开发支持&#xff0c;以及代码压缩混淆、处理浏览…

自定义序列化

3.2.2.自定义序列化 RedisTemplate可以接收任意Object作为值写入Redis&#xff1a; 只不过写入前会把Object序列化为字节形式&#xff0c;默认是采用JDK序列化&#xff0c;得到的结果是这样的&#xff1a; 缺点&#xff1a; 可读性差内存占用较大 我们可以自定义RedisTempla…

NASA数据集——2015 年30 米分辨率的地衣地面覆盖率模型估计值

cABoVE: Lichen Forage Cover over Fortymile Caribou Range, Alaska and Yukon, 2000-2015 文件修订日期&#xff1a;2021-07-21 数据集版本: 1 摘要 本数据集提供了美国阿拉斯加东部内陆和加拿大育空地区 Fortymile 研究区 2015 标称年 30 米分辨率的地衣地面覆盖率模型估…

modbus代码思路整理

void main() { eMBinit(); eMBEnable();/*1.eRcvState = STATE_RX_INIT 2.USART:USART_RX->Enable & USART_TX->Disable 3.打开TIM(5ms):Enable 4.eMBState = STATE_ENABLE*/ while(1) {…

YOLOv8-ROS-noetic+USB-CAM目标检测

环境介绍 Ubuntu20.04 Ros1-noetic Anaconda-yolov8虚拟环境 本文假设ROS和anaconda虚拟环境都已经配备&#xff0c;如果不知道怎么配备可以参考&#xff1a; https://blog.csdn.net/weixin_45231460/article/details/132906916 创建工作空间 mkdir -p ~/catkin_ws/srccd ~/ca…

SQL注入四-PHP应用SQL二次注入堆叠执行DNS带外功能点黑白盒条件

演示案例&#xff1a; PHP-MYSQL-二次注入-DEMO&74CMSPHP-MYSQL-堆叠注入-DEMO&CTF强网PHP-MYSQL-带外注入-DEMO&DNSLOG #PHP-MYSQL-二次注入-DEMO&74CMS 1、DEMO-用户注册登录修改密码 2、CMS-74CMS个人中心简历功能 黑盒思路&#xff1a;分析功能有添加后对数…

dom元素+CSS实现阶梯动画效果

1.效果 2.代码实现 <template><div class"container"><div class"Box"><div class"box" style"background-color: red;"></div><div class"box" style"background-color: orange;&q…

湖北专升本报名照片需要<40kb怎么解决

湖北专升本报名照片需要<40kb怎么解决

vue 修改element-plus主题色

一、安装SCSS npm install sass --save-dev npm install sass-loader --save-dev npm install node-sass --save-dev npm install vue-style-loader --sava-dev 二、添加主题文件theme.scss forward "element-plus/theme-chalk/src/common/var.scss" with ($col…

特种兵旅游-扬州、南京

一、扬州 Day01 西安咸阳机场->扬州泰州机场&#xff08;扬州地界但是离泰州也嘎嘎近&#xff09;->大运河博物馆&#xff08;需要提前预约&#xff01;&#xff09;&#xff08;超级震撼&#xff09; Day02 瘦西湖&#xff08;门票有点贵&#xff0c;但是蛮值得&#x…

kubernetes负载均衡-service

一、service的概念 1、什么是service 在Kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;当我们需要访问这个应用时&#xff0c;可以通过Pod的IP进行访问&#xff0c;但是这里有两个问题:1、Pod的IP地址不固定&#xff0c;一旦Pod异常退出、节点故障&#xff0c;则会…