【C++ 进阶】继承

2023-11-15

一.继承的定义格式

基类又叫父类,派生类又叫子类;


二.继承方式

继承方式分为三种:

     1.public继承

     2.protected继承

     3.private继承

基类成员与继承方式的关系共有9种,见下表:

 虽然说是有9种,但其实最常用的还是红框里的,其它的很少用。

 总结

1. 基类private成员在派生类中无论以什么方式继承都是不可见的

    不可见指:基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不       管在类里面还是类外面都不能去访问它;

2.如果想要在派生类访问基类中的成员变量,可以在基类中定义为 protected 成员

3.基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式)

4.使用关键字class时默认的继承方式是private

   使用struct时默认的继承方式是public


三.派生类和基类之间的赋值转换

 1.派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用,这个过程又被形象的称为      切片/切割

2.基类对象不能赋值给派生类对象

3.基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的;


四.隐藏(重定义)

1.子类和父类中,只要函数名相同就构成隐藏

2.成员名相同也构成隐藏;

3.在子类成员函数中,可以使用 基类::基类成员 显示访问隐藏的函数或成员;

4.最好不要定义同名的成员变量。

隐藏(重定义)与重载

重载:在同一作用域

隐藏:在不同的作用域,一个在父类,一个在子类


五.派生类中的默认成员函数

1.构造函数

   派生类必须先自动调用基类的默认构造(初始化基类的那一部分成员),如果基类没有默     认构造,就要在派生类的初始化列表阶段显式调用基类的构造函数,然后派生类调用自己     的构造函数。

2.拷贝构造

   派生类的拷贝构造必须先调用基类的拷贝构造完成基类的拷贝初始化。

3.赋值重载

   派生类赋值重载必须先调用基类的赋值重载完成基类的复制。

4.析构函数

   销毁对象时,会先调用派生类的析构函数,然后再自动调用基类的析构函数,这样就保证     了析构的顺序(即先子后父)

   如果不是这个顺序,一个成员可能会析构两次,就会导致程序崩溃,比如以下的代码:

class A
{
public:
	~A()
	{
		delete _a;
	}

	int* _a = new int;
};

class B :public A
{
public:
	~B()
	{
		delete _b;  
		A::~A();   //显式调用父类的析构函数,在调用完后,编译器又会自动调用一次父类的析构函数, 
                   //导致父类成员_a析构了两次,从而程序崩溃
	}

	int* _b = new int;
};

int main()
{
	A  a;
	B b;
	return 0;
}

六.继承与友元,静态成员

 友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员;

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例 ,静态成员不属于任何一个具体的实例对象,而是属于类本身,子类可以继承父类的静态成员,而不需要重新定义。


七.多继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

下面就是一个多继承:

class A
{};

class B
{};

class C:public A,public B   //多个父类之间用逗号隔开
{};

多继承的一个坑:菱形继承

 上图就构成了一个菱形继承,它会导致两个问题:

   1.数据冗余,因为会存两个Person类;

   2.二义性

class A
{
public:
	int _a;
};

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

class C :public A
{
public:
	int _c;
};

class D :public B, public C
{
public:
	int _d;
};

int main()
{
	D d;
	d._a;   //二义性问题,不知道访问的是哪个_a;
    d.A::_a;   //显式访问,解决了二义性问题,但无法解决数据冗余问题

	return 0;
}

虚拟继承:解决菱形继承问题

在菱形继承的腰部加上 virtual  关键字构成虚拟继承

如将上面代码class B 和  class C  改成:

class B: virtual public A   //虚拟继承
{};

class C: virtual public A
{};

原理

通过观察菱形继承和虚拟继承的内存窗口我们发现:

 

 


八.总结和反思

1.public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象

2.组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象

例如:

class A
{};

class B
{
    A a;   //组合
};

3.组合的耦合性比继承低,所以一般推荐使用组合。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++ 进阶】继承 的相关文章

随机推荐

  • 警告:检测到时钟错误。您的创建可能是不完整的。

    问题 make 2 Warning File CMakeFiles MultiCol SLAM dir depend make has modification time 24688 s in the future make 2 警告 检测
  • 模式识别 - 名词解释整理

    模式识别 模式识别是指把对象根据其特征归到若干类别中适当的一类 模式识别也称为模式分类 模式 模式是指因素间存在确定性或随机性规律的对象 过程或事件的集合 识别 识别就是把对象分门别类地认出来 样本 sample 所研究对象的一个个体 样本
  • Python3中参数*args和**kwargs介绍

    在Python中 我们可以使用两种特殊符号将可变数量的参数传递给函数 args和 kwargs 你可以使用任何单词代替args和kwargs 但通常做法是使用args和kwargs args允许函数接受任意数量的位置参数 positiona
  • vue学习-01vue入门

    Vue官网地址 https cn vuejs org Vue介绍 Vue 读音 vju 类似于 view 是一套用于构建用户界面的渐进式框架 与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用 Vue 的核心库只关注视图层 不仅易
  • C++模拟鼠标移动及单击实现代码

    摘要 本文分享了如何通过代码实现重复点击按钮 要实现该功能有个关键点需要注意 许多软件的按钮不是一个窗口 所以无法通过枚举窗口或者查找子窗口来定位按钮 本文通过直接定位按钮位置来避免这个问题 该程序的使用方法 管理员运行程序 移动鼠标指针到
  • C++ 预处理器

    http www runoob com cplusplus cpp preprocessor html
  • 虚拟专用网之L2TP协议介绍

    目录 L2TP简介 L2TP构建图解 L2TP建立及拆除流程 L2TP隧道的建立 L2TP会话的建立 L2TP隧道和会话维护和拆除流程 L2TP协议栈结构及数据包的封装过程 L2TP隧道和会话的验证过程 L2TP和PPTP的区别 L2TP简
  • z字形扫描

    z字形扫描 类别 数组 时间限制 1S 内存限制 256Kb 问题描述 在图像编码的算法中 需要将一个给定的方形矩阵进行Z字形扫描 Zigzag Scan 给定一个m n的矩阵 Z字形扫描的过程如下图所示 对于下面给出的4 4的矩阵 1 5
  • android studio从git上克隆项目显示the directory already exists and it is not empty

    英文的意思能看懂 文件夹已存在并且不为空 但是网上百度了一下貌似没有完完整整是这句话的问题 我还纳闷怎么克隆不下来 我是想把项目克隆下来到workspace里面 workspace里面本来就还有其他项目在 原来克隆操作不会帮你生成跟目录 你
  • Android 10.0 系统settings详情页 卸载修改为停止,禁止卸载app功能实现

    1 概述 在10 0的系统rom定制化功能的开发过程中 在一些系统预安装的app中 在Launcher3中可以通过拖拽然后卸载 这个限制卸载可以在前面的博客中禁止卸载这些预安装的app 然后就需要在系统Settings详情页来禁止app的卸
  • C语言 用户输入运算数和四则运算符,输出计算结果

    用C语言中简单的语句可以实现四则运算 1 if语句 include
  • 翻译 第11章 of IEEE Std 1666-2011 IEEE Standard for Standard SystemC Language Reference Manual

    11 TLM 2 0 core interfaces 11 TLM 2 0 核心接口 In addition to the core interfaces from TLM 1 TLM 2 0 adds blocking and non b
  • 如何把笔记本做台式机的副屏(一套键鼠控制两台电脑)

    通过一套键鼠控制两台电脑 前提 安装所需的软件 一 简介 二 安装 2 1 小技巧 前提 两台电脑在同一个局域网内 并且均为windows操作系统 例如两台电脑链接的同一个WIFI 或者笔记本无线连接路由 台式机插网线链接路由 只有在同一个
  • 史上最全排序算法全面总结

    考察点 在信息学奥赛初赛中对于排序算法的考察主要体现在以下几方面 1 时间复杂度 2 稳定性 3 最坏情况下移动次数 4 移动次数与关键字顺序关系 先看熟记知识点 1 关于稳定性 假定在待排序的记录序列中 存在多个具有相同的关键字的记录 若
  • 指针空间的申请和释放

    http blog csdn net netanimals article details 6530787
  • 若依跨域解决

    发现接口取消权限校验之后 跨域调用还是失败了 若依本身有跨域配置 注释掉换为新的 若依原跨域配置 ResourcesConfig 中 跨域配置 Bean public CorsFilter corsFilter CorsConfigurat
  • matlab中常用符号

    在使用MATLAB的过程中 经常需要对输出图形中的变量进行标注 其中经常遇到的难题就是如何标注各种上标 下标 斜体 黑体 箭头 上圆圈 正负号等特殊符号 以及如何标注特殊的数学符号 这里第一机电网给大家总结一下 希望对大家有用 一 MATL
  • 奥林巴斯新微单E-M5II曝光:合金机身可防水

    通常单反相机是专业摄影师的最佳工具 但是对于普通消费者来说 既要拥有专业的图像质量 又不想负担单反相机沉重的质量 就成为了基本的要求 因此 微单相机就在这种情况下应运而生 如果你还没决定好选择哪一款微单 那么奥林巴斯即将推出的这款OM D
  • Android APP性能及专项测试

    Android篇 1 性能测试 Android性能测试分为两类 1 一类为rom版本 系统 的性能测试 2 一类为应用app的性能测试 Android的app性能测试包括的测试项比如 1 资源消耗 2 内存泄露 3 电量功耗 4 耗时 5
  • 【C++ 进阶】继承

    一 继承的定义格式 基类又叫父类 派生类又叫子类 二 继承方式 继承方式分为三种 1 public继承 2 protected继承 3 private继承 基类成员与继承方式的关系共有9种 见下表 虽然说是有9种 但其实最常用的还是红框里的
Powered by Hwhale