C++系列-继承补充

news2024/12/26 11:38:40

🌈个人主页:羽晨同学 

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

继承和友元

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

比如在这个例子当中:

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.coloradmin.cn/o/2186022.html

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

相关文章

主流HR软件对比,五大系统功能与成本一览

五款主流HR系统包括ZohoPeople、金蝶人力云、用友人力云、红海eHR和SAPSuccessFactors&#xff0c;各具特色。ZohoPeople功能丰富&#xff0c;金蝶人力云云端部署&#xff0c;用友人力云多模块集成&#xff0c;红海eHR定制化服务&#xff0c;SAPSuccessFactors全球化视野。企业…

docker pull 超时Timeout失败的解决办法

当国内开发者docker pull遇到如下提示时&#xff0c;不要惊讶 [rootvm /]# docker pull postgres Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 128.121.146.235:443: i/o timeout [rootvm /]# 自2024…

BIOSCAN:农业生产中昆虫图像识别数据集(猫脸码客 第202期)

BIOSCAN&#xff1a;大型手工标记昆虫图像识别数据集 引言 随着科技的飞速发展&#xff0c;特别是计算机视觉和深度学习技术的日益成熟&#xff0c;图像识别在多个领域展现出强大的应用潜力。在生物学领域&#xff0c;图像识别技术不仅能够提高物种分类的效率和准确性&#x…

魔方的顶层拼法

找十字 直线对准自己&#xff0c;顺时针90&#xff0c;上左下右&#xff0c;逆时针90旋转回来。 找鱼头 少两三个点的时候&#xff0c;左后方要放一点黄色&#xff08;顶面颜色&#xff09; 下右上右下右右上 少四个点的时候&#xff0c;后面不能放黄色。 找到小于之后&am…

(11)(2.1.3) KDE CAN ESCs(二)

文章目录 前言 4 配置 5 记录和报告 6 参数说明 前言 KDECAN ESC 是高端 ESC&#xff0c;允许使用自定义 CAN 协议进行控制和反馈。 4 配置 设置 CAN_D1_PROTOCOL 8&#xff08;KDECAN&#xff09;&#xff1b;设置 CAN_P1_DRIVER 1&#xff08;第一个驱动程序&#xf…

Sui主网升级至V1.34.2

Sui主网现已升级至V1.34.2版本&#xff0c;同时协议升级至60版本。其他升级要点如下所示&#xff1a; 协议 #19014: 在验证Groth16 zk-proof时对无效公共输入进行快速判断。添加了一个新的Move函数flatten&#xff0c;可将向量中的向量展平成单个向量&#xff0c;这在新协议…

客运自助售票系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;乘客管理&#xff0c;司机管理&#xff0c;车票信息管理&#xff0c;订单信息管理&#xff0c;退票信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;车票信息&#…

YOLOv11目标检测实战2:人流统计、车流统计和跟踪(附源码)

目录 一、演示效果 二、基础理论和核心概念 三、安装环境和依赖 四、工作流程和步骤 五、核心部分源码&#xff1a; 六、总结 一、演示效果 二、基础理论和核心概念 YOLOv11 是 YOLO 系列的最新版本&#xff0c;它不仅在目标检测方面表现出色&#xff0c;还引入了对象分割…

linux和windows系统使用k8s控制节点的kubernetes资源

一般linux获取master控制节点的授权&#xff1a; [rootharbor ~]# vim /etc/hosts 192.168.1.30 harbor 192.168.1.50 master 192.168.1.51 node-0001 192.168.1.52 node-0002 192.168.1.53 node-0003 192.168.1.54 node-0004 192.168.1.55 node-0005#下…

PostgreSQL升级:使用pg_upgrade进行大版本(16.3)升级(17.0)

1.pg_upgrade工具介绍 pg_upgrade 会创建新的系统表&#xff0c;并以重用旧的数据文件的方式进行升级。 pg_upgrade 的参数选项如下&#xff1a; -b bindir&#xff0c;--old-bindirbindir&#xff1a;旧的 PostgreSQL 可执行文件目录&#xff1b; -B bindir&#xff0c;--new-…

CleverPDF是一款专业的pdf转换器-强大的PDF表格识别能够将PDF中的表格提取到Excel或者其他格式-供大家学习研究参考

提供了更多的输出选项来满足您不同的PDF转换需求&#xff0c;强大的PDF表格识别能够帮助您准确地将PDF中的表格提取到Excel或者其他格式。另外CleverPDF无需上传文件到互联网&#xff0c;直接在您的本地电脑处理PDF&#xff0c;让您更放心地转换或编辑隐私或者保密的文档&#…

CSS——文字闪烁效果

CSS——文字闪烁效果 今天来完成一个文字闪烁的动态效果&#xff0c;具体呈现效果如下&#xff1a; 文字闪烁动态效果 实现步骤 基础的样式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"vi…

Android Context是什么?有很多的context他们之间有什么区别?什么时候该使用哪个?

目录 一、Context是什么&#xff1f; 在Android中&#xff0c;Context是一个抽象类 &#xff0c;它代表了应用程序的当前状态&#xff0c;包括资源和类加载器等&#xff0c;它提供了一个应用运行所需的信息&#xff0c;比如我们要获取资源 &#xff0c;那么需要她&#xff0c;…

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

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

Python使用matplotlib绘制五星红旗

安装包 pip install matplotlib pip install numpy完整代码 import matplotlib.pyplot as plt import numpy as np# 设置画布尺寸 fig plt.figure(figsize(10, 7)) ax fig.add_subplot(111)# 绘制红色背景 ax.set_facecolor(red)# 五星红旗的尺寸定义 flag_width 30 flag_…

云岚到家xxl job 配置

调度中心&#xff1a; 负责管理调度信息&#xff0c;按照调度配置发出调度请求&#xff0c;自身不承担业务代码&#xff1b; 主要职责为执行器管理、任务管理、监控运维、日志管理等 任务执行器&#xff1a; 负责接收调度请求并执行任务逻辑&#xff1b; 主要职责是执行任…

文章解读与仿真程序复现思路——高电压技术EI\CSCD\北大核心《适用于并联构网型储能系统的协调有功控制策略设计》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

解决OpenCV保存视频 视频全部为绿色的bug

目录 项目场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 项目场景&#xff1a; 使用OpenCV-Python 保存视频&#xff0c;视频为numpy array格式&#xff0c;保存的视频全部为无意义的绿色。 问题描述 用opencv 保存的视频会出现全部为绿色的情况&…

Webpack模式-Resolve-本地服务器

目录 ResolveMode配置搭本地服务器区分环境配置 Resolve 前面学习时使用了各种各样的模块依赖&#xff0c;这些模块可能来自于自己编写的代码&#xff0c;也可能来自第三方库&#xff0c;在 Webpack 中&#xff0c;resolve 是用于解析模块依赖的配置项&#xff0c;它决定了 We…

FTP应用篇:低功耗4G模组Air780EP AT开发

低功耗4G模组Air780EP支持全系列的AT指令以及LuatOS脚本二次开发。 今天我们详细讲解Air780EP模组FTP应用的多个AT命令示例。 本文同样适用于以下型号&#xff1a; Air700ECQ/Air700EAQ/Air700EMQ Air780EQ/Air780EPA/Air780EPT/Air780EPS Air780E/Air780EX/Air724UG… 一、相…