c++之旅第七弹——继承

大家好啊,这里是c++之旅第七弹,跟随我的步伐来开始这一篇的学习吧!

如果有知识性错误,欢迎各位指正!!一起加油!!

创作不易,希望大家多多支持哦!

一.继承和派生:(实质上是一个过程,不过是从不同角度来看的)

1.继承方式:

单继承:

class A
{};
class B:public A
{};

多继承:

class D
{};
class E
{};
class F:public D,public E
{};

多级继承:

class A
{};
class B:public A
{};
class C:public B
{};
class D:public C
{};
//多级继承,
//D 拥有了 A,B,C 的所有属性

2.继承涉及的属性问题:

(1)以上的继承动作属性都是公有,不过还有和类中成员相同的其他属性:私有和保护

继承时基类中的成员属性和继承动作的属性是一起决定派生类中的成员属性的,两者同时考虑,那个更严格派生类中该成员的属性就是哪个属性(私有>保护>公有),所以一般使用公有继承,这样可以保留原来基类中成员的原有属性不变

(2)如果基类中某一成员是私有属性,那么无论使用那种继承方式,在派生类中也是无法进行直接访问的,要访问也只能通过公有接口来进行访问,如果类B继承类A时继承方式是私有,而基类A中成员的属性为公有,那么在派生类B中是可以进行基类A中该成员的访问的,而当派生类C继承B时使用任何继承方式都无法对基类A中的该成员进行访问,这是因为B继承A时使用私有继承方式,相当于A类是B类的私有属性成员。

(3)保护属性成员可以在派生类中进行访问,但是不可以在派生类的派生类中进行访问

(4)基类如果是带参构造,在派生类通过成员初始化列表进行构造函数的调用:

class B :public A
{int d;
public:B(int i) :A(i)//基类如果是带参构造,在派生类通过成员初始化列表进行构造函数的调用{d = 3;}~B(){}
};

3.有关继承和派生中的内存问题:

(1)派生类可以作为基类对象,基类对象不可以作为派生类对象,也就是进行赋值操作,这是因为派生类的内存是大于基类的内存的,用派生类对象来给基类对象进行赋值可以使基类对象中的内存都放满,剩余的不属于基类,放不进去也无所谓;而如果将基类赋值给派生类对象时,就会出现派生类对象的内存有空缺,无法表示派生类,所以这种赋值是无法进行的。

(2)若使用多级继承,那么最终的类类型对象的成员在内存中的表现为嵌套时最内部的类的成员是储存在最终的派生类对象中最前面的内存区域

三,继承之后:派生类可以继承父类中的所有数据成员和函数成员除了构造和析构函数,这是属于类自身的,无法进行继承

(1)继承之后派生类的构成:继承时如果基类和派生类中有同名的成员,在派生类中进行调用时优先调用派生类中的成员,局部优先于全局,如果想要调用的是基类中的成员,那么需要使用类名作用域来进行调用,因为包含一个无名的对象,无法使用对象名作用域来进行访问,使用类名作用域代替之,多继承同样可以使用类名作用域来进行成员的访问

//继承时的访问:
class CA
{
protected:int a;
public:CA(){a = 10;}
};
​
class CB : public CA
{int a;
public:CB(){CA::a = 123;//在CB对象里面包含一个无名的CA对象,所以只能通过类型去作用域访问a = 20;}
};

(2)在定义一个派生类对象时,其构造顺序为先构造基类对象,然后再在基类的基础上构造派生类对象,也就是调用构造函数的顺序,然后当程序运行结束时(假设是在栈区的对象)析构函数是反向来进行析构的,这和栈结构有关,但是在堆区进行以上操作时,也是遵循以上规律(构造是通过new开辟堆区内存,析构是手动使用delete来进行指针的删除)

四, 菱形继承:一个基类(共同基类)派生出两个类(间接基类),这两个类再进行多继承至一个类(最终类)

1.菱形继承虚继承时两个间接基类都要写virtual关键字,这样才能起到虚继承应该起到的作用,否则还是会进行共同基类的二次拷贝,因为写了virtual关键字才可以使间接基类拥有多的四个字节,有指针的作用,可以寻找共同基类是否已经构造过,从而避免多次拷贝

2.虚继承间接基类中多的四字节相当于是指针,可以用来寻找共同基类是否已经构造过了,若构造过就不会再次构造,这样可以减少当共同基类内存大时的没有必要的二次拷贝内存

3.尽量不写菱形继承,因为会引起一些问题,主要包括以下几点原因:

(1)虚基类冗余数据:在菱形继承中,由于共同基类被多次继承,会导致虚基类中的数据在派生类中存在多份冗余拷贝,增加了内存消耗。

(2)构造函数调用顺序不明确:在菱形继承中,由于存在多条继承路径,构造函数的调用顺序可能变得复杂,不易理解和维护。

(3)内存布局不清晰:由于存在多份冗余数据和多条继承路径,菱形继承的内存布局变得复杂,容易引起内存对齐、访问越界等问题。

(4)代码可读性差:菱形继承会增加代码的复杂性,降低代码的可读性和可维护性,使程序难以理解和调试。

如果一定要写,尽量使用虚继承方式

4.构造顺序:虚基类->基类->派生类,虚基类的无名对象是在继承的最终类对象中的最后部分的内存,且只有一份它的内存。

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

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

相关文章

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:WaterFlow)

瀑布流容器,由“行”和“列”分割的单元格所组成,通过容器自身的排列规则,将不同大小的“项目”自上而下,如瀑布般紧密布局。 说明: 该组件从API Version 9 开始支持。后续版本如有新增内容,则采用上角标单…

change buff 与buffer_pool详解

buffer_pool的结构: change buff: 其中保存的是修改操作的动作 在查询的时候,change buffer是没有办法和innodb_buffer_pool查询一样缓存有数据直接返回的,因为change buffer记录的是修改操作这 个动作,并不是修改后的数据,所以即便change buffer中已经…

Airbnb将禁止在房源内安装监控摄像头

在面临隐私问题后,Airbnb 最近更新了政策,全面禁止房东在出租屋内安装并使用室内安全监控摄像头。 修订后的政策将在全球范围内适用,并将于4 月 30 日生效。Airbnb 表示,做出这一改变是为了优先考虑客人的隐私并简化安全摄像头的规…

算法之前缀和

题目1: 【模板】一维前缀和(easy) 方法一: 暴力解法, 时间复杂度O(n*q), 当n10^5, q 10^5, 时间复杂度为O(10^10), 会超时. 方法二: 前缀和: 快速求出数组中某一段连续区间的和. 第一步: 预处理出来一个前缀和数组dp: 1. dp[i]表示区间[1,i]里所有元…

visual studio2019项目中引入头文件失效问题的解决

这几天把项目整理一下,但在引入头文件过程中非常曲折。 项目本身写好了可以运行,但是项目结构是这样的: 所以想把功能模块化,同一类协议功能放在一起。 于是建包,创建文件,导入头文件: 在新…

数据结构:详解【链表】的实现(单向链表+双向链表)

目录 一,前言二 ,有关链表的概念,结构和分类三,无头单向非循环链表(单链表)1.单链表的功能2.单链表功能的实现3.完整代码 四,带头双向循环链表(双链表)1.单链表与双链表的…

代码随想录算法训练营三刷day25 | 回溯 之 216.组合总和III 17.电话号码的字母组合

三刷day25 216.组合总和III剪枝 17.电话号码的字母组合 216.组合总和III 题目链接 解题思路: 选取过程如图: 图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。 递归三部曲 确定递归函数参…

科研学习|论文解读——交替协同注意力网络下基于属性的情感分析 (IPM, 2019)

论文题目 Aspect-based sentiment analysis with alternating coattention networks 摘要 基于属性的情感分析(ABSA)旨在预测给定文本中特定目标的情感极性。近年来,为了获得情感分类任务中更有效的特征表示,人们对利用注意力网络…

【学习学习】学习金字塔

学习金字塔(Cone of Learning),全称学习吸收率金字塔,是一种现代学习方式的理论。网上流传它是美国缅因州的国家训练实验室(National Training Laboratories)研究成果,用数字形式形象显示了采用…

19. UE5 RPG使用GameplayEffect的Attribute Based Modifiers

前几篇文章我也说了GE的基础使用,但是,对一些属性的应用没有述说,后续,我将一点一点的将它们如何使用书写下来。 这一篇,主要就讲解一下Attribute Based Modifiers使用,先说一下它的应用场景,一…

蓝桥集训之糖果

蓝桥集训之糖果 核心思想:dfs 剪枝 重复覆盖问题 暴搜 直到所有列都覆盖优化: 1.迭代加深 答案从1开始 2.逻辑简化 每次从可选行数最少得一列开始 3.可行性剪枝 添加估值函数h(),表示至少还需要选几行 与剩余行数的大小比较 4.**位运算 **将每包糖果…

32程序结构学习

初始化代码 void LED_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;/*开启GPIOC的外设时钟*/RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); /*选择要控制的GPIOC引脚*/ GPIO_InitStructur…