C++学习笔记(十二)------is_a关系(继承关系)

你好,这里是争做图书馆扫地僧的小白。
个人主页:争做图书馆扫地僧的小白_-CSDN博客
目标:希望通过学习技术,期待着改变世界。
提示:以下是本篇文章正文内容,下面案例可供参考
文章目录
前言
一、继承关系的语法形式
(一)单继承的语法格式:
(二)多继承的语法形式
(三)单继承关系举例
二、继承关系的意义
三、继承关系的权限问题
四、单继承
(一)单继承关系下的内存布局
1.举个例子,代码如下:
2.图解如下:
(二)自动隐藏机制
(三)继承关系下的类型兼容规则
五、多继承
(一)多继承举例说明:
(二)多继承的内存布局
总结
前言
随着技术的革新,出现各种各样的编程语言,C++就是其中之一,作为最受欢迎的编程语言之一,C++带给开发者们最大的惊喜便是其强大的特性。一方面跟C兼容,可以直面系统底层API,SDK,另一方面提供了很多范式,足够的抽象能力,面向对象,操作符重载,模板等。
之前的C++学习笔记(十一)------has_a和use_a关系-CSDN博客已经讲解了has_a和use_a关系,本篇将讲解最为重要的一种关系即is_a关系(继承关系)。
一、继承关系的语法形式
(一)单继承的语法格式:
class 子类 : 继承权限 + 父类
{//继承即是子类继承了父类中的所有属性与方法(构造函数除外)
};
(二)多继承的语法形式
class 子类 : 继承权限1,父类1,继承权限2,父类2,... 继承权限n,父类n
{//子类继承多个父类中的所有属性与方法。
}
注意:继承关系中,子类并不继承父类中的构造函数。因为构造函数是特别的为本类域进行初始化的函数,并不会被继承。子类中要有子类的默认构造或自定义有参构造。
多继承一般情况不使用,如果使用多用于集成多个抽象类,原因见下文的多继承部分。
(三)单继承关系举例
#include <iostream>
using namespace std;
class Car
{
public:int price;
public:void run(){cout << "汽车在行驶" << endl;}
};
class BYD : public Car
{
public:void uniqueEmblem(){cout << "有着中国特色的车标" << endl;}
};
int main()
{BYD byd;byd.run();byd.price;byd.uniqueEmblem();return 0;
}
二、继承关系的意义
继承关系的意义是:代码复用性与高拓展性。
使用继承关系的步骤:首先把这类的事件抽象出来一些共有的属性与特征,把它们定义为父类。再用这个父类,对具有不同特点的子类进行派生,就可以派生出各种不同的子类。这样的子类有着公有的属性,还有着各自独特的性质。
三、继承关系的权限问题
#include <iostream>
using namespace std;class Car
{
public:int price;
public:void run(){cout << "汽车在行驶" << endl;}
};class BYD : private Car
{
public:void uniqueEmblem(){cout << "有着中国特色的车标" << endl;}
};int main()
{BYD byd;byd.run();byd.price;byd.uniqueEmblem();return 0;
}
继承关系图如下所示,如图所示当子类继承父类时,可以理解为将父类整体打包,将其作为一整个属性赋给子类。
注意:每一种继承关系对父类各种权限的属性的访问也是有区别的。当public继承时,对父类中private权限的属性不管是在子类的类外还是类内都没有访问权限;对父类中protected权限的属性在子类的类内有访问权限且为protected访问权限,在子类类外没有访问权限;对父类中public属性的属性不管是在子类类内还是类外都是public访问权限。其余两种不在采用文字形式进行描述,详细的直观的描述见下面的表格。


四、单继承
(一)单继承关系下的内存布局
子类对象被构造时,先构造父类,然后再调用子类的构造完成对子类类域中拓展的属性进行初始化,此时,子类的对象具有具体初始值。析构的时候先析构子类,然后在析构父类。
注意的是子类析构被执行,父类析构也一定被析构。原因是内存绑定
1.举个例子,代码如下:
#include <iostream>
using namespace std;
class Car
{
private:int price;
public:void run(){cout << "汽车在行驶" << endl;}Car(){cout << "Car父类的构造" << endl;}~Car(){cout << "Car父类的析构" << endl;}
};
class BYD : private Car
{
public:BYD(){cout << "BYD子类的构造" << endl;}~BYD(){cout << "BYD子类的析构" << endl;}
};int main()
{BYD byd;return 0;
}
2.图解如下:

(二)自动隐藏机制
当子类中有与父类同名属性或函数时,父类中的同名属性或行为将自动隐藏在自己的父类的类域之中,如果想访问父类类域之中的属性或行为,就使用域名::访问。
举个例子,代码如下:
#include <iostream>
#include <unistd.h>
using namespace std;
class Car
{
public:int price = 10000;
public:void run(){cout << "车子正在行驶之中" << endl;}Car(){cout << "Car父类的构造" << endl;}~Car(){cout << "Car父类的析构" << endl;}
};class BYD : public Car
{
public:int weight = 20000;
public:void run(){cout << "BYD高速行驶" << endl;}BYD(){cout << "BYD子类的构造" << endl;}~BYD(){cout << "BYD子类的析构" << endl;}
};
int main()
{BYD byd;cout << byd.Car::price << endl;byd.run();byd.Car::run();return 0;
}
(三)继承关系下的类型兼容规则
在之前我们学到当使用指针的时候,要保证等号前后的指针类型要相同才可以,在继承中不然。继承关系中父类指针或者引用可以安全的指向或者引用子类类型的对象,但是子类指针或者引用并不能指向或者引用父类类型的对象。
需要注意的是使用父类指针在释放资源时,注意要强转成子类指针才可以完全释放,不然会造成资源的泄露。
还需要注意的是当父类中只有有参构造的时候,子类的构造函数处应该进行初始化列表的操作,指定父类的有参构造对其进行初始化操作,否则会报错。
举个例子,代码如下:
#include <iostream>
#include <unistd.h>
using namespace std;
class Car
{
public:int price = 10000;
public:void run(){cout << "汽车在行驶" << endl;}Car(int price){cout << "Car父类的构造" << endl;}~Car(){cout << "Car父类的析构" << endl;}
};
class BYD : public Car
{
public:int price = 20000;
public:void run(){cout << "BYD高速行驶" << endl;}BYD():Car(1) {cout << "BYD子类的构造" << endl;}~BYD(){cout << "BYD子类的析构" << endl;}
};
int main()
{//栈上定义对象BYD byd;Car* c = &byd; //父类属性的指针可以安全的指向子类属性c->run(); //调用父类中子类和父类公有的run方法cout << c->price << endl; //10000Car& ref_c = byd; //父类属性的引用可以安全的指向子类属性ref_c.run(); //调用父类中子类和父类公有的run方法cout << ref_c.price << endl; //10000//用堆上的对象:Car* ptr_c = new BYD();ptr_c->run();delete (BYD*)ptr_c; //释放指针时,需要进行强转,否则只采用delete ptr_c,只会析构父类,而子类指向的堆上资源并没有被回收return 0;
}
五、多继承
在多继承时,虽然多继承可以大在提高代码的复用性,但是会造成代码冗余,当多个父类中有同名函数或属性时,在访问时候会出现二义性的问题。
需要注意使用类域::访问的方式进行指定访问,但是这样给程序设计带来很多不便,所以多继承在开发时尽量避免。如果一定要使用多继承时,推荐使用多继承多个抽象类,因为抽象类一般都没有具体的属性,只有纯虚函数。
(一)多继承举例说明:
#include <iostream>
using namespace std;
class Phone
{
public:int power;
public:void sendMessage(){cout << "发消息" << endl;}
};
class Pad
{
public:int power;
public:void playGame(){cout << "玩游戏" << endl;}
};
class Computer : public Phone, public Pad
{};
int main()
{Computer computer;computer.sendMessage();computer.playGame();cout << computer.Phone::power << endl; cout << sizeof(Computer) << endl;return 0;
}
(二)多继承的内存布局

注意:当上述例子中定义Phone *p = &computer 和 Pad *p1 = &computer 这两个指针指向的地址空间是否一致?
答案是不一致的,当使用父类指针指向子类时,在继承中父类指针永远指向的是自己类中的起始地址。
当然多继承也符合继承关系下的类型兼容规则。
总结
以上就是今天要讲的内容,本文将is_a关系(继承关系)进行了详细的介绍,分成了单继承和多继承,并对继承中权限问题和内存布局进行了详细的介绍,当然多继承中还存在着一种特殊的构造形式即为菱形继承,这部分将留作下篇笔记进行撰写。
相关文章:
C++学习笔记(十二)------is_a关系(继承关系)
你好,这里是争做图书馆扫地僧的小白。 个人主页:争做图书馆扫地僧的小白_-CSDN博客 目标:希望通过学习技术,期待着改变世界。 提示:以下是本篇文章正文内容,下面案例可供参考 文章目录 前言 一、继承关系…...
DC电源模块的设计与制造技术创新
BOSHIDA DC电源模块的设计与制造技术创新 DC电源模块的设计与制造技术创新主要涉及以下几个方面: 1. 高效率设计:传统的DC电源模块存在能量转换损耗较大的问题,技术创新可通过采用高效率的电路拓扑结构、使用高性能的功率开关器件和优化控制…...
Sketch for Mac:实现你的创意绘图梦想的矢量绘图软件
随着数字时代的到来,矢量绘图软件成为了广告设计、插画创作和UI设计等领域中必不可少的工具。在众多矢量绘图软件中,Sketch for Mac(矢量绘图软件)以其强大的功能和简洁的界面脱颖而出,成为了众多设计师的首选。 Sket…...
ReactNative0.73发布,架构升级与更好的调试体验
这次更新包含了多种提升开发体验的改进,包括: 更流畅的调试体验: 通过 Hermes 引擎调试支持、控制台日志历史记录和实验性调试器,让调试过程更加高效顺畅。稳定的符号链接支持: 简化您的开发工作流程,轻松将文件或目录链接到其他…...
SVN忽略文件的两种方式
当使用版本管理工具时,提交到代码库的文档我们不希望存在把一些临时文件也推送到仓库中,这样就需要用到忽略文件。SVN的忽略相比于GIT稍显麻烦,GIT只需要在.gitignore添加忽略规则即可。而SVN有两种忽略方式,一个是全局设置&#…...
手写VUE后台管理系统10 - 封装Axios实现异常统一处理
目录 前后端交互约定安装创建Axios实例拦截器封装请求方法业务异常处理 axios 是一个易用、简洁且高效的http库 axios 中文文档:http://www.axios-js.com/zh-cn/docs/ 前后端交互约定 在本项目中,前后端交互统一使用 application/json;charsetUTF-8 的请…...
JavaScript装饰者模式
JavaScript装饰者模式 1 什么是装饰者模式2 模拟装饰者模式3 JavaScript的装饰者4 装饰函数5 AOP装饰函数6 示例:数据统计上报 1 什么是装饰者模式 在程序开发中,许多时候都我们并不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就…...
C++学习笔记01
01.C概述(了解) c语言在c语言的基础上添加了面向对象编程和泛型编程的支持。 02.第一个程序helloworld(掌握) #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std;//标准命名空间int main() {//co…...
【UE5】初识MetaHuman 创建虚拟角色
步骤 在UE5工程中启用“Quixel Bridge”插件 打开“Quixel Bridge” 点击“MetaHumans-》MetaHuman Presets UE5” 点击“START MHC” 在弹出的网页中选择一个虚幻引擎版本,然后点击“启动 MetaHuman Creator” 等待一段时间后,在如下页面点击选择一个人…...
物流实时数仓:数仓搭建(DWD)一
系列文章目录 物流实时数仓:采集通道搭建 物流实时数仓:数仓搭建 物流实时数仓:数仓搭建(DIM) 物流实时数仓:数仓搭建(DWD)一 文章目录 系列文章目录前言一、文件编写1.目录创建2.b…...
MATLAB安装
亲自验证有效,多谢这位网友的分享: https://blog.csdn.net/xiajinbiaolove/article/details/88907232...
C语言——预处理详解(#define用法+注意事项)
#define 语法规定 #define定义标识符 语法: #define name stuff #define例子 #include<stdio.h> #define A 100 #define STR "abc" #define FOR for(;;)int main() {printf("%d\n", A);printf("%s\n", STR);FOR;return 0; } 运行结果…...
Linux(23):Linux 核心编译与管理
编译前的任务:认识核心与取得核心原始码 Linux 其实指的是核心。这个【核心(kernel)】是整个操作系统的最底层,他负责了整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等&a…...
Oracle RAC环境下redo log 文件的扩容
环境: 有一个2节点RAC每一个节点2个logfile group每一个group含2个member每一个member的大小为200M 目标:将每一个member的大小有200M扩充到1G。 先来看下redo log的配置: SQL> select * from v$log;GROUP# THREAD# SEQUENCE# …...
Java入门学习笔记一
一、Java语言环境搭建 1、JAVA语言的跨平台原理 1.1、什么是跨平台性? 跨平台就是说,同一个软件可以在不同的操作系统(例如:Windows、Linux、mad)上执行,而不需要对软件做任务处理。即通过Java语言编写的…...
分布式块存储 ZBS 的自主研发之旅|元数据管理
重点内容 元数据管理十分重要,犹如整个存储系统的“大黄页”,如果元数据操作出现性能瓶颈,将严重影响存储系统的整体性能。如何提升元数据处理速度与高可用是元数据管理的挑战之一。SmartX 分布式存储 ZBS 采用 Log Replication 的机制&…...
六大设计原则
六大设计原则 1、单一职责原则 一个类或者模块只负责完成一个职责或者功能。 2、开放封闭原则 规定软件中的对象、类、模块和函数对扩展应该是开放的,对于修改应该是封闭的。用抽象定义结构,用具体实现扩展细节。 3、里氏替换原则 如果S是T的子类型…...
dockerfile创建镜像 lNMP+wordpress
dockerfile创建镜像 lNMPwordpress nginx dockernginx mysql dockermysql php dockerphp nginx vim nginx.conf vim Dockerfile docker network create --subnet172.17.0.0/16 --opt "com.docker.network.bridge.name""docker1" mynetwork docker buil…...
深入理解——快速排序
目录 💡基本思想 💡基本框架 💡分割方法 ⭐Hoare版本 ⭐挖坑法 ⭐前后指针法 💡优化方法 ⭐三数取中法 ⭐小区间内使用插入排序 💡非递归实现快速排序 💡性能分析 💡基本思想 任取待排…...
【代码随想录】算法训练计划50
dp 1、123. 买卖股票的最佳时机 III 题目: 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意:你不能同时参与多笔交易(你必须在再次购…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
