当前位置: 首页 > news >正文

C++ - 继承

继承的基本概念

继承就是一种代码的复用.
子类通过继承父类, 就能使用父类的变量, 方法.

学生和老师这两种身份, 他们都有共同的属性: 他们都有名称, 年龄, 性别 ....

当然他们也有各种独有的属性, 学生有学号, 老师有工号 ....

对于这些共有的属性, 我们可以将它们提取出来:

class person
{public:string name;string sex;int age;
};

然后让学生类和老师类去继承这个 person 类.

class student : public person
{
public:string student_ID; // 学号
};
class teacher : public person
{
public:string job_ID;
};

class student : public person

student: 派生类 (又称为子类)

public: 继承方式

person: 基类 (又称为父类)

现在实例化出一个 student 对象之后, 这个对象也有 person 中的属性.

student st;
st.name = "张三";
st.age = 14;
st.student_ID = "123456";

继承关系和访问限定符

C++ 中存在三种访问限定符

  • private: 只能在类内访问
  • protected: 允许类内和派生类 (子类) 访问
  • public: 无论类内类外都可以访问

那么当这三种访问限定符用在继承中, 有什么样的效果.

子类继承父类时, 会继承父类的成员属性和成员方法.
继承存在自己的继承关系 (private ...), 属性和方法也有自己的访问修饰限定符.
这两者之间的关系是如何的呢?

结论: 取 继承关系的限定符 和 访问修饰限定符中, 权限小的那一个

class person
{
public:int a;
protected:int b;
public:int c;
};// 1. public 继承
class student1 : public person
{//父类所有的属性都会被继承
public:int a;
protected: // protect 和 public 取权限小的那一个int b;
};// 2. private 继承
class student2 : private person
{
private: // private 和 public 取权限小的那一个int a;
private:int b;
};

我们可以看到, 继承得到的属性和方法的访问限定符, 是取二者之间较小的那一个.

但是在上面的两个继承的 student 类中, 我没有将变量 c 写出来, 这是为什么?
很简单, 变量 c 由 private 修饰, 所以只能在 person 中访问, 即便 student 继承了 person,
student 是独立的, 不是 person 的一部分, 也就无法访问 c.

一般而言, 都是使用 public 继承.

这里用一张图来表明继承后的方法和属性的访问权限

 继承的作用域

从上面的成员的继承, 我们能察觉到, 派生类和基类是两个不同的空间.

那么既然是不同的空间, 在派生类中, 就可以定义和父类一样的成员属性和成员方法.

class person
{
public:int add(int a, int b){}string name;int age;
};class student : public person
{
public:int add(){return person::add(10, 20);}string name;
};student st;
st.name; // 就近原则, 默认访问子类的
st.person::name; // 带上基类的作用域, 才会访问到基类的属性

在同一个作用域中, 是不能存在两个同名变量的, 但是派生类和基类是不同的作用域. 他们的作用域都是独立的.
所以, 在派生类和基类中定义名称相同的变量也是可以的. (但是在实际使用中, 是不推荐这样写的)

那么这里就有一个很容易犯错的点. 上面代码中的 add 函数, 是不是构成了重载?
当然不是, 重载的条件之一就是: 同名函数处于同一作用域, 派生类和基类属于不同作用域.
当然也就不构成重载. 

事实上, 这种情况称为隐藏 (也成为重定义). 在子类成员函数中,可以使用 基类::基类成员 访问.

父子类的对象赋值转换

  • 子类对象赋值给基类的 对象/基类指针/基类引用
  • 父类对象不能赋值给派生类对象

因为子类拥有父类的所有属性和方法, 父类赋值给子类, 就是把子类中, 父类的那部分给切出来.

这个过程称为"切片".

子类中的默认成员函数

  • 子类的构造/拷贝构造/赋值重载函数, 都需要去调用父类的构造/拷贝构造/赋值重载.
  • 子类的析构函数, 会自动的调用父类的析构函数, 所以不用显示的写出来
  • 当实例化一个子类对象时, 会先初始化父类的成员变量, 然后再初始化子类的成员变量
  • 当析构一个子类对象时, 会先调用子类的析构函数, 然后再调用父类的析构函数. (与构造函数调用顺序相反)

下面代码可以通过打印顺序观察各自的调用顺序.

class person
{
public:person(const char* name = "parent"):_name(name){cout << "person()" << endl;}person(const person& p){_name = p._name;cout << "person(const person&)" << endl;}person& operator= (const person& p){cout << "person operator=" << endl;if(this != &p){_name = p._name;}return *this;}~person(){cout << "~person()" << endl;}
private:string _name
};class student : public person
{
public:student(const char* name, int age):person(name),_age(age){cout << "student()" << endl;}student(const student& st):person(s),_age(st._age){}student& operator= (const student& st){cout << "student operator=" << endl;person::operator=(st);_age = st._age;return *this;}~student(){cout << "~student" << endl;}
private:int _age;
};int main()
{student s1("zhangsan", 10);student s2(s1);student s3("lisi", 20);s1 = s3;return 0;
}

菱形继承和虚继承

在C++中, 允许一个派生类继承多个基类, 这样会导致一个问题.

那么此时问题来了, D同时继承了 B和C, B和C 都继承了A.
那么D中就存在两份类A的成员属性, 一份来自B, 一份来自C.

此时D中就多余了一份数据, 占用了额外的空间.
更重要的是, 造成了二义性. 当我们访问继承至类A的属性时,
访问的是通过B继承得来的, 还是通过继承C得来的. 无法区分.

所以这里就引出了一个方法来解决这个菱形继承的问题.

虚继承: 在 B, C 继承前加上 virtual 关键字.

class A
{int a;
};class B : virtual public A
{int b;
};class C : virtual public A
{int c;
};class D : public B, A
{int d;
};

virtual 关键字要加在 B, C前, 而不是 D 前.

在实际写代码中, 是很少会使用多继承的, 这样带来的不可控影响太大了.
所以在实际写代码中, 能不用多继承就不用多继承. 这部分了解即可

相关文章:

C++ - 继承

继承的基本概念 继承就是一种代码的复用. 子类通过继承父类, 就能使用父类的变量, 方法. 学生和老师这两种身份, 他们都有共同的属性: 他们都有名称, 年龄, 性别 .... 当然他们也有各种独有的属性, 学生有学号, 老师有工号 .... 对于这些共有的属性, 我们可以将它们提取出来: …...

华为服务器使用U盘重装系统

一、准备工作 下载官方系统&#xff08;注意服务器CPU的架构是x86-64还是aarch64&#xff0c;不然可能报意想不到的错&#xff09;制作启动U盘&#xff08;下载rufus制作工具&#xff0c;注意文件系统选FAT32还是NTFS&#xff09; 二、安装步骤 将U盘插入USB接口重启服务器…...

网络分层模型( OSI、TCP/IP、五层协议)

1、网络分层模型 计算机网络是一个极其复杂的系统。想象一下最简单的情况&#xff1a;两台连接在网络上的计算机需要相互传输文件。不仅需要确保存在一条传输数据的通路&#xff0c;还需要完成以下几项工作&#xff1a; 发起通信的计算机必须激活数据通路&#xff0c;这包括发…...

前端开发 之 15个页面加载特效上【附完整源码】

文章目录 一&#xff1a;彩球环绕加载特效1.效果展示2.HTML完整代码 二&#xff1a;跷跷板加载特效1.效果展示2.HTML完整代码 三&#xff1a;两个圆形加载特效1.效果展示2.HTML完整代码 四&#xff1a;半环加载特效1.效果展示2.HTML完整代码 五&#xff1a;音乐波动加载特效1.效…...

Spring Boot使用JDK 21虚拟线程

JDK 21引入的虚拟线程&#xff08;Virtual Threads&#xff09;是 Project Loom 的一部分&#xff0c;旨在显著简化并发编程并提高 Java 应用的可扩展性。以下是虚拟线程的主要特点&#xff1a; 1. 概念 虚拟线程是轻量级线程&#xff0c;与传统的操作系统线程不同&#xff0…...

《从0到1常用Map集合核心摘要 + 不深不浅底层核心》

《从0到1常用Map集合核心摘要不深不浅底层核心》 前置知识 什么是键值对 ​ 键值对是一种数据结构&#xff0c;键是唯一标识&#xff0c;值是对应数据&#xff0c;用来快速查找信息。例&#xff1a; {"name": "Alice"}&#xff0c;键是name&#xff0c;…...

12 设计模式之工厂方法模式

一、什么是工厂方法模式&#xff1f; 1.定义 在软件开发中&#xff0c;设计模式 是解决常见软件设计问题的最佳实践。而 工厂方法模式&#xff08;Factory Method Pattern&#xff09; 作为创建型设计模式之一&#xff0c;常常被用来解决对象创建问题。它通过将对象的创建交给…...

spaCy 入门与实战:强大的自然语言处理库

spaCy 入门与实战&#xff1a;强大的自然语言处理库 spaCy 是一个现代化、工业级的自然语言处理&#xff08;NLP&#xff09;库&#xff0c;以高效、易用和功能丰富著称。它被广泛应用于文本处理、信息提取和机器学习任务中。本文将介绍 spaCy 的核心功能&#xff0c;并通过一…...

python包的管理和安装——笔记

1.列出包 pip list pip freeze 用这2个可以查看当前python 下所有的包和版本&#xff0c;还有下载地址 如果只是想导出当前的环境 可以用 2.安装pipreqs pip install pipreqs&#xff0c;pipreqs ./可以导出当前项目的包这个包 遇到编码报错 pipreqs ./ --encodingutf8 p…...

Vue前端页面内嵌套本项目iframe窗口的通信传输方式

一、目的 想要在iframe中使用本项目页面、并能够与其父页面组件实现实时通信。Vue前端页面内嵌套本项目iframe窗口的通信传输方式-星林社区 https://www.jl1mall.com/forum/PostDetail?postId20241202172800023969 二、iframe通信方式 1.接收消息 页面需要监听 message 事件…...

【WEB开发.js】addEventListener事件监听器的绑定和执行次数的问题(小心踩坑)

假设我们有一个按钮&#xff0c;用户点击该按钮后&#xff0c;会选择一个文件&#xff0c;且我们希望每次点击按钮时只触发一次文件处理。下面我会给你一个简单的例子&#xff0c;展示放在函数内部和放在函数外部的区别。 1. 将事件监听器放在函数内部&#xff08;问题的根源&…...

用于LiDAR测量的1.58um单芯片MOPA(一)

--翻译自M. Faugeron、M. Krakowski1等人2014年的文章 1.简介 如今&#xff0c;人们对高功率半导体器件的兴趣日益浓厚&#xff0c;这些器件主要用于遥测、激光雷达系统或自由空间通信等应用。与固态激光器相比&#xff0c;半导体器件更紧凑且功耗更低&#xff0c;这在低功率供…...

【GPT】代谢概念解读

以下是对代谢中分解代谢和合成代谢两个概念的深入解读&#xff0c;用简单易懂的方式展开说明&#xff1a; 1. 分解代谢&#xff08;Catabolism&#xff09; 什么是分解代谢&#xff1f; 分解代谢是身体把大分子“拆开”的过程。就像把一个三明治分解成面包片、肉片和菜叶&#…...

Devops-git篇-01-git环境配置

环境配置 设置用户签名 配置用户名&#xff1a; git config --global user.name 你的用户名 配置邮箱&#xff1a; git config --global user.email 注册的邮箱 配置好之后&#xff0c;可以用git config --global --list命令查看配置是否OK $ git config --global --list u…...

STM32 HAL库开发学习1.STM32CubeMX 新建工程

STM32 HAL库开发学习1.STM32CubeMX 新建工程 一、 STM32 CubeMX 下载二、CubeMX 功能介绍1. 固件包路径设置2. 新建工程 三、创建项目实例1. 新建项目2. GPIO 管脚设置3. GPIO 窗口配置4. 调试设置5. 时钟配置6. 项目管理&#xff08;1&#xff09;项目信息&#xff08;2&#…...

JS学习(2)(浏览器执行JS过程、JS的ECMAScript、DOM、BOM)

目录 一、浏览器如何执行JS&#xff1f; &#xff08;1&#xff09;浏览器主要的组成部分。 1、渲染引擎。 2、JS引擎。 &#xff08;2&#xff09;演示。 二、JS的组成。 &#xff08;1&#xff09;JS主要由三部分组成。 1、JS基础。 2、JS-API。 &#xff08;2&#xff09;EC…...

如何解决服务器扫描出的ASP木马问题

随着互联网的发展&#xff0c;网站安全问题日益凸显。其中&#xff0c;ASP&#xff08;Active Server Pages&#xff09;木马因其隐蔽性和危害性成为攻击者常用的手段之一。本文将详细介绍如何检测和清除服务器上的ASP木马&#xff0c;以保障网站的安全。 1. ASP木马概述 ASP…...

SpringBoot 架构助力夕阳红公寓管理系统可持续发展战略

摘 要 如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为了解决现有问题而产生的。针对于夕阳红公…...

TCP、HTTP、RPC

一、TCP (Transmission Control Protocol) 定义 TCP&#xff08;传输控制协议&#xff09;是一种面向连接、可靠传输的传输层协议&#xff0c;用于在计算机网络中提供端到端的数据通信服务。它是互联网协议套件的一部分&#xff0c;与IP&#xff08;互联网协议&#xff09;一…...

《C++ 中 RNN 及其变体梯度问题的深度剖析与解决之道》

在当今人工智能蓬勃发展的浪潮中&#xff0c;递归神经网络&#xff08;RNN&#xff09;及其变体长短期记忆网络&#xff08;LSTM&#xff09;和门控循环单元&#xff08;GRU&#xff09;在处理序列数据方面展现出了强大的潜力。然而&#xff0c;当我们在 C中着手实现这些网络时…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...