C++系列-继承补充

🌈个人主页:羽晨同学 

💫个人格言:“成为自己未来的主人~”  

继承和友元

友元关系不能继承,父亲的朋友不能是你的朋友

比如在这个例子当中:

class Student;
class Person
{
public:friend void Display(const Person& p, const Student& s);
protected:string _name;//姓名
};
class Student :public Person
{
public://friend void Display(const Person& p, const Student& s);
protected:int _stuNum;
};
void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
}
int main()
{Person p;Student s;Display(p,s);return 0;
}

这个访问p._name是没有问题的,但是访问s._stuNum是会发生报错的,因为友元函数不能被继承,所以基类也就不能访问子类的私有和保护的成员。

那怎么样才能解决这个问题呢?

答案其实很简单,那就是:让孩子自己和朋友培养关系,也就是说,在派生类中再次写一次友元函数的声明。

class Student;
class Person
{
public:friend void Display(const Person& p, const Student& s);
protected:string _name;//姓名
};
class Student :public Person
{
public:friend void Display(const Person& p, const Student& s);
protected:int _stuNum;
};
void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
}
int main()
{Person p;Student s;Display(p,s);return 0;
}

这样子,就不会发生报错了。

继承和静态成员

基类定义的静态成员,那么不管是基类还是派生类都只有这样一个静态成员,也就是说,静态成员是不会继承的。具体我们来看下面的代码:

class Person
{
public:Person(){++_count;}
protected:string _name;
public:static int _count;
};
int Person::_count = 0;
class Student :public Person
{
protected:int _stuNum;
};
int main()
{Person p;Student s;cout << &Person::_count << endl;cout << &Student::_count << endl;return 0;
}

我们可以看到的是,不管是基类的_count还是派生类的_count,它们的地址是相同的。所以,我们可以得到的是,静态成员修饰的变量或者函数是不会参与继承的。

菱形继承和菱形虚拟继承

单继承

一个子类只有一个父类,叫做单继承。

多继承

一个子类有多个父类,这是多继承

菱形继承

菱形继承是多继承的一种特殊情况。

 

菱形继承的问题:数据冗余和二义性。怎么说呢,其实看上面的图,我们可以看到,Person的信息其实被Student和Teacher继承了一次,说明在Student和Teacher中都有Person的信息,当Assistant继承Student和Teacher的时候,继承了两次Person的信息,这就造成了数据的冗余和二义性。

 数据冗余和二义性

你看,在下面代码中同时存在数据冗余和二义性的问题:

class Person
{
public:string _name;int _id;int _tel;int _adress;
};
class Student :  public Person
{
protected:int _num;
};
class Teacher :  public Person
{
protected:int _id;
};
class Assistant :public Student, public Teacher
{
protected:string _majorCourse;
};
int main()
{Assistant a;a._name = "peter";return 0;
}

当我们运行这个代码的时候,是会报错的,原因是因为并不知道_name具体指向的是什么,其实这个很好解决,我们只要在前面加上特定类域的声明就可以了.比如:

int main()
{Assistant a;a.Teacher::_name = "peter";a.Student::_name = "jijiao";return 0;
}

但是这样子的话,其实数据冗余的问题是没有办法解决的,那我们应该怎么处理呢,这个时候就需要用到虚拟继承了。

虚拟继承是可以解决二义性和数据冗余的问题的,我们只要在第一次继承的前面加上virtual就可以避免这些问题。

class Person
{
public:string _name;int _id;int _tel;int _adress;
};
class Student : virtual public Person
{
protected:int _num;
};
class Teacher :  virtual public Person
{
protected:int _id;
};
class Assistant :public Student, public Teacher
{
protected:string _majorCourse;
};
int main()
{Assistant a;a._name = "peter";return 0;
}

这样,这个代码就没问题了。

很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂,所以一般不建议设计出多继承,一定不要涉及出菱形继承,否则在复杂度及性能上都有问题。

多继承可以认为是C++的缺陷之一。

在实践中,尽可能的使用多继承,而不是菱形继承。

继承和组合

  • public继承是一种is-a的关系,也就是说每个派生类对象都是一个基类对象
  • 组合式一种has-a的关系,假设B组合了A,每个B对象都有一个A对象
class Tire
{
protected:string _brand = "Michelin";//品牌size_t _size = 17;//尺寸
};
//组合
class Car
{
protected:string colour = "白色";//颜色string _num = "陕ABIT00";//车牌号Tire _t;
};

你看,在这个里面,轮胎和车并不是is-a的关系,不能说轮胎是车,也不能说车是轮胎,只能说车里面有轮胎。这个就是组合。

在代码关系当中,代码和代码之间的耦合度越低越好,所以,我们尽量使用组合,而不是继承。

虚拟继承解决数据冗余和二义性的原理

为了研究虚拟继承原理,我们给出了一个简化的菱形继承体系,再借助内存窗口观察对象成员的模型。虚拟继承是实现了一个虚表,然后在虚表里面存放了虚函数的地址的指针,然后虚函数在代码段中实现。

好了,本次的文章就到这里了,我们下次再见。 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

厦门网站设计的用户体验优化策略

厦门网站设计的用户体验优化策略 在信息化快速发展的今天&#xff0c;网站作为企业与用户沟通的重要桥梁&#xff0c;用户体验&#xff08;UX&#xff09;的优化显得尤为重要。尤其是在交通便利、旅游资源丰富的厦门&#xff0c;吸引了大量企业进驻。在这样竞争激烈的环境中&am…

netty之NettyServer字符串编码器

前言 netty通信就向一个流水channel管道&#xff0c;我们可以在管道的中间插入一些‘挡板’为我们服务。比如字符串的编码解码&#xff0c;在前面我们使用new StringDecoder(Charset.forName(“GBK”))进行字符串解码&#xff0c;这样我们在收取数据就不需要手动处理字节码。那…

linux文件编程_进程通信

1.进程间通信介绍 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同进程之间传播或交换信息。 进程是操作系统的概念&#xff0c;每当我们执行一个程序时&#xff0c;对于操作系统来讲就创建了一个进程&#xff0c;在这个过程中&…

已解决:org.springframework.web.HttpMediaTypeNotAcceptableException

文章目录 写在前面问题描述报错原因分析&#xff1a; 解决思路解决办法1. 确保客户端请求的 Accept 头正确2. 修改 Controller 方法的 produces 参数3. 配置合适的消息转换器4. 检查 Spring 配置中的媒体类型5. 其他解决方案 总结 写在前面 在开发过程中&#xff0c;Spring 框…

C++容器之list基本使用

目录 前言 一、list的介绍&#xff1f; 二、使用 1.list的构造 2.list iterator的使用 3.list capacity &#x1f947; empty &#x1f947;size 4.list element access &#x1f947; front &#x1f947; back 5.list modifiers &#x1f947; push_front &#x1f947; po…

从零到一构建解释器-【1-基础概念】

文章目录 扫描器词法分析语法分析 静态分析中间代码优化代码生成运行时单遍编译器数遍历解释器转译器即使编译编译器与解释器 本教程参考【手搓解释器】 这里只是过一遍基本概念&#xff0c;后面会有涉及到具体解析 扫描器 词法分析 接受字符流忽略无意义符号&#xff0c;如…

【Git】一文看懂Git

Git 一、简介1. Git 与 SVN 区别1.1 Git 是分布式的&#xff0c;SVN 不是1.1.1 分布式版本控制系统Git1.1.2 集中式版本控制系统SVN 1.2 Git 把内容按元数据方式存储&#xff0c;而 SVN 是按文件1.3 Git 分支和 SVN 的分支不同1.4 Git 没有一个全局的版本号&#xff0c;而 SVN …

《Windows PE》3.2.4节表

节表由多个节表项&#xff08;IMAGE_SECTION_ HEADER&#xff09;组成&#xff0c;每个节表项&#xff08;40个字节&#xff09;记录了 PE中与某个特定的节有关的信息&#xff0c;如节的属性、节 的大小、在文件和内存中的起始位置等。节表中节的数量由字段IMAGE_FILE_HEADER. …

迷宫中的最短路径:如何用 BFS 找到最近出口【算法模板】

如何通过广度优先搜索&#xff08;BFS&#xff09;求解迷宫问题 在这篇文章中&#xff0c;我们将学习如何使用 广度优先搜索&#xff08;BFS&#xff09; 解决一个典型的迷宫问题&#xff0c;具体是从迷宫的一个入口出发&#xff0c;找到最近的出口。我们将一步步分析 BFS 是如…

超声波扫描显微镜SAM有什么作用?

知识星球里的学员问&#xff1a;在晶圆厂中很少见到超声波扫描显微镜&#xff0c;但是在封测厂中会经常用到&#xff0c;麻烦讲一下超声波扫描显微镜的原理与用途 什么是超声波扫描显微镜&#xff1f; 超声波扫描显微镜&#xff0c;英文名scanning acoustic microscope&#…

【论文阅读】Equivariant Multi-Modality Image Fusion(CVPR2024)

Equivariant Multi-Modality Image Fusion&#xff08;CVPR2024&#xff09; 现有方法存在的问题 由于现实中没有一种传感器可以同时捕捉所有模态的信息&#xff0c;因此缺乏真实的融合图像作为训练的参照标准&#xff0c;这对深度学习模型的训练带来了挑战。 基于生成对抗网…

2024 全新体验:国学心理 API 接口来袭

在当今快节奏的生活中&#xff0c;人们对于心理健康越来越重视。而研究发现&#xff0c;国学心理学乃至传统文化中的思想智慧&#xff0c;对于人们的心理健康有着独特且深远的影响。为了让更多人能够体验到国学心理的魅力&#xff0c;2024年全新推出的国学心理 API 接口&#x…

基于单片机的两轮直立平衡车的设计

本设计基于单片机设计的两轮自平衡小车&#xff0c;其中机械部分包括车体、车轮、直流电机、锂电池等部件。控制电路板采用STC12C5A60S2作为主控制器&#xff0c;采用6轴姿态传感器MPU6050测量小车倾角&#xff0c;采用TB6612FNG芯片驱动电机。通过模块化编程完成了平衡车系统软…

变电站红外检测数据集 1180张 变电站红外 标注voc yolo 13类

变电站红外检测数据集 1180张 变电站红外 标注voc yolo 13类 变电站红外检测数据集 名称 变电站红外检测数据集 (Substation Infrared Detection Dataset) 规模 图像数量&#xff1a;1185张图像。类别&#xff1a;13种设备类型。标注个数&#xff1a;2813个标注。 数据划分…

关于TF-IDF的一个介绍

在这篇文章中我将介绍TF-IDF有关的一些知识&#xff0c;包括其概念、应用场景、局限性以及相应的代码。 一、概念 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种广泛用于信息检索和文本挖掘中的统计方法&#xff0c;用于评估一个词在一个文…

鸿蒙ArkUI实战开发-主打自研语言及框架

ArkUI 是 HarmonyOS 的声明式 UI 开发框架&#xff0c;而 ArkUI-X 是基于 ArkUI 框架扩展而来的跨平台开发框架。ArkUI-X 支持 HarmonyOS、OpenHarmony、Android 和 iOS 平台&#xff0c;允许开发者使用一套代码构建支持多平台的应用程序。 一、ArkUI-X 的实战开发步骤 在实战开…

存储主动防御,为什么Gartner技术曲线尤为重视?

【科技明说 &#xff5c; 科技热点关注】 近来&#xff0c;从Gartner发布的2024年存储技术成熟曲线&#xff08;Hype Cycle for Storage Technologies ,2024&#xff09;的相关报告看出&#xff0c;到2028年&#xff0c;所有存储产品都将融入专注于数据主动防御的网络存储功能&…

西电25考研 VS 24考研专业课大纲变动汇总

01专业课变动 西安电子科技大学专业课学长看到953网络安全基础综合变为 893网络安全基础综合&#xff0c;这是因为工科要求都必须是8开头的专业课&#xff0c;里面参考课本还是没变的&#xff0c;无非就是变了一个名字 对于其他变动专业课也是同理的 02专业课考纲内容变化 对于…

深度学习笔记18_TensorFlow实现猫狗识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 一、我的环境 1.语言环境&#xff1a;Python 3.9 2.编译器&#xff1a;Pycharm 3.深度学习环境&#xff1a;TensorFlow 2.10.0 二、GPU设置…

【拥抱AIGC】通义灵码策略配置

通义灵码企业级策配置支持智能问答、行间代码生成安全过滤器相关策略配置。 适用版本 企业标准版、企业专属版 通义灵码管理员、组织内全局管理员&#xff08;专属版&#xff09;在通义灵码控制台的策略配置中进行安全过滤器的配置&#xff0c;开启后&#xff0c;企业内开发…