c++-----继承

news2024/10/6 20:25:32

01:继承是什么

定义

继承 (inheritance) 机制是面向对象程序设计 使代码可以复用 的最重要的手段,它允许程序员在 持原有类特性的基础上进行扩展 ,增加功能,这样产生新的类,称派生类。继承 呈现了面向对象 程序设计的层次结构 ,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用, 承是类设计层次的复用
简单来说,继承是实现代码复用的一种手段。

继承的语法

继承权限可以不写,使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public不过 最好显示的写出继承方式

打个比方

我们要实现一个学生类和一个老师类

class student {
	int name;					//姓名
	char Date_of_birth[32];		//出生日期
	char Origin[32];			//籍贯
	//.......

	long long School_Degree;	//学号
	long long Dormitory_number;	//宿舍号
	//........
};
class teacher {
	int name;					//姓名
	char Date_of_birth[32];		//出生日期
	char Origin[32];			//籍贯
	//.......

	char Graduation_school[32];	//毕业学校
	char posts[32];				//职位
	//........
};

可以看出老师类与学生类有很多相同的内容,如果要在两个类中都写个add函数的话,两个函数会有很多相同之处.这实在不够优雅,所以c++的祖师爷搞出来继承这套东西.

//个人类
class Person {
	int name;					//姓名
	char Date_of_birth[32];		//出生日期
	char Origin[32];			//籍贯
	//.......
};
//学生类,学生类依赖于个人类
class student : public Person
{
	long long School_Degree;	//学号
	long long Dormitory_number;	//宿舍号
	//........
};
//老师类,老师类依赖于个人类
class teacher : public Person
{
	char Graduation_school[32];	//毕业学校
	char posts[32];				//职位
	//........
};

子类中可以按照相应的权限来使用父类的内容


02.继承关系与访问限定符

3种继承关系:public, protected ,private与3种访问限定符:public, protected ,private.总共能组合出九种访问权限.

继承关系与访问限定符的关键字字符一样,但书写位置不同,含义不同.

巧记:

  1. 基类的private在派生类都是不可见的.
  2. public>protected>private,基类的非private元素取继承关系与访问限定符较小的为权限.

举个例子

class parent {
public:
	int pub;
protected:
	int pro;
private:
	int pri;
};
class child :public parent{		//以共有的方式继承
	void fun()
	{
		pub = 1;	//	public和public	->公有继承
		pro = 2;	//	public和protected	->保护继承
		//pri = 3;	//	父类为private	->在子类中不可见,访问会报错
	}
};

最常见的继承方式是公有继承

父类的私有元素是否会被子类继承?

以上段代码为例,我们来使用一下sizeof()

一个int为4字节,打印的12证明child继承到了三个父类元素,也就代表子类会继承父类元素

给父类写一个构造函数,通过内存窗口也能看到

结论:子类会继承父类的全部元素,但是父类的私有元素不可访问

03:子类与父类的赋值转换

子类可以直接给父类赋值,这个过程叫做切片,(请注意父类不可给子类复制,当然有手动重载的除外)

父类及父类的指针,父类的引用都可直接由对应的子类赋值.子类的指针可以通过父类指针强制类型转换来赋值,但是有越界的可能

例:

class Person {
	string _name;
	int _sex;
	int _age;
};
class Student : public Person {
	long long _no;
};
int main()
{
	Person p;
	Student s;
	Person* pp = &s;
	Person& tmp = s;
	Person qp = s;

    Student* ss = (Student*)&p;//有可能越界

	return 0;
}

04:继承的作用域

在继承的体系中,父类和子类有相互独立的作用域.

当子类和父类有同名函数时,会构成隐藏,请注意,隐藏只与函数名有关,与参数和返回值无关!!!!

默认调用的时子类函数,可以通过加上作用域来指定作用域

子类与父类最好不要定义重名函数


05.子类的默认成员函数

有的人死了,但他还活着!有的人活着,但他已经死了!       

                                                                                                                                      ----鲁迅

不知道大家自类和对象之后再次看到默认成员函数是什么感觉,反正我有点心肌梗塞,你先别怕,怕了也学不会其实这里的要比类和对象里的简单一些.

  1. 构造函数:调用子类的构造函数时必须要调用父类的构造函数,如果父类没有默认构造函数,那么在初始化子类时必须显式的调用父类的构造函数
  2. 子类的拷贝构造必须要调用父类的拷贝构造.而在子类的构造函数中给父类元素赋值
  3. 子类operator=函数必须调用父类的operator=完成赋值,而非直接访问父类元素
  4. 子类的析构在调用完之后会自动的去调用父类的析构,子类的析构中不需要显示调用父类的析构
  5. 子类的构造会先调用父类的构造函数
  6. 子类的析构会最后调用父类的析构函数

06.继承与友元

父类的友元不是子类的友元函数,也就是说父类友元不能直接访问子类保护和私有

class Student;
class Person
{
public:
 friend void Display(const Person& p, const Student& s);
protected:
 string _name; // 姓名
};
class Student : public Person
{
protected:
 int _stuNum; // 学号
};
void Display(const Person& p, const Student& s) {
 cout << p._name << endl;
 cout << s._stuNum << endl;     //不是子类友元,这里不能访问
}

07:父类与静态成员

在父类中定义的静态成员,当父类被继承到子类时,所有的子类都会只使用一个静态成员.

class A {
public:
	static int a;
};
class B : public A {
public:
	void fun() {
		cout << "在B中查看全局变量a,a的值为:"<< a << endl;
	}
};
class C : public A {
public:
	void fun() {
		cout << "在C中查看全局变量a,a的值为:" << a << endl;
	}
};
int A::a = 0;
int main() {
	A aa;
	B bb;
	C cc;
	cout << "A中aa的值改为0" << endl;
	bb.fun();
	cc.fun();
	aa.a = 10;
	cout << "A中aa的值改为10" << endl;
	bb.fun();
	cc.fun();
	system("pause");
	return 0;
}

08.多继承

多继承与单继承

单继承很好理解,譬如学生是一个人,,那么学生类就可以做人类类的子类,二者关系为单继承.

多继承可以理解为在学生和人类的基础之上,学生张三是一名某某游戏会员,那么在描述张三时,可以让张三继承两个类,这样一个子类对应多个父类,他们的关系为多继承.

Java是没有的多继承的,由此可见c++这门语言是一门旷世神作,c++程序员都聪明绝顶,Java语言过于局限,Java程序员好逸恶劳(手动滑稽),多继承毫无疑问是有现实意义的,譬如有些博士生既是老师又是学生,谷爱凌既是中国人又是美国人,马克思既是犹太人又是中国人(不是),如果使用多继承的话可以很好的实现一些面向对象功能,但是毫无疑问在后续使用菱形继承之类复杂继承时,出现了很多语法困难,c++早期版本也是一直在改进继承.

总之,多继承是有他独特的意义的,是值得学习的

多继承语法

语法很简单:在单继承的基础之上加个逗号,再加上第二个父类即可

菱形继承

可以看出,在Student类和Teacher类中都有Person类,进而在Assistant类中会有两份Person类,这就造成了代码冗余,因为两个Person中的数据很显然是一模一样的

ps:棱形继承要访问Person元素的话,需要在前面加上父类作用域,否则编译器分不清是在操作哪个Person

class Person
{
public :
 string _name ; // 姓名
};
class Student : public Person
{
protected :
 int _num ; //学号
};
class Teacher : public Person
{
protected :
 int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
 string _majorCourse ; // 主修课程
};
void Test ()
{
 // 这样会有二义性无法明确知道访问的是哪一个
 Assistant a ;
a._name = "peter";
// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决
 a.Student::_name = "xxx";
 a.Teacher::_name = "yyy"; }

虚拟继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在 Student
Teacher 的继承 Person 时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地
方去使用。
class Person
{
public :
 string _name ; // 姓名
};
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 ; // 主修课程
};
void Test ()
{
 Assistant a ;
 a._name = "peter"; }

虚拟继承的底层原理(vs2022编译器32位)

这是一些简单的类构成的菱形继承.

class A {
public:
 int _a;
};
// class B : public A
class B : virtual public A {
public:
 int _b;
};
// class C : public A
class C : virtual public A {
public:
 int _c;
};
class D : public B, public C {
public:
 int _d;
};
int main()
{
 D d;
 d.B::_a = 1;
 d.C::_a = 2;
 d._b = 3;
 d._c = 4;
 d._d = 5;
 return 0; }

首先是非虚函数,看以看到A存了两份,有数据冗余的情况

虚函数,看以看到A只存了一份

可以看出,虚函数通过存储指针->偏移量来找到二者共有的A的地址

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

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

相关文章

Java springboot使用EasyExcel读Excel文件,映射不到属性值,对象属性值都是null

如果你的类上有这个注解&#xff0c;去掉火或注释掉就可以了 Accessors(chain true)解决方法

常用日期组件封装

date.js // 获取近期日期数组 例&#xff1a;["2024-04-04 00:00:00", "2024-04-05 23:59:59"] const getDateRange (num 1) > {const time1 new Date()const diff new Date().getTime() - 86400000 * (num)const time2 new Date(diff)const year…

Canvas使用详细教学:从基础绘图到进阶动画再到实战(海报生成、Flappy Bird 小游戏等),掌握绘图与动画的秘诀

一、Canvas基础 1. Canvas简介 Canvas是HTML5引入的一种基于矢量图形的绘图技术&#xff0c;它是一个嵌入HTML文档中的矩形区域&#xff0c;允许开发者使用JavaScript直接操作其内容进行图形绘制。Canvas元素不包含任何内在的绘图能力&#xff0c;而是提供了一个空白的画布&a…

LLM-01 大模型 本地部署运行 ChatGLM2-6B-INT4(6GB) 简单上手 环境配置 单机单卡多卡 2070Super8GBx2 打怪升级!

写在前面 其他显卡环境也可以&#xff01;但是最少要有8GB的显存&#xff0c;不然很容易爆。 如果有多显卡的话&#xff0c;单机多卡也是很好的方案&#xff01;&#xff01;&#xff01; 背景介绍 目前借到一台算法组的服务器&#xff0c;我们可以查看一下目前显卡的情况 …

一篇出色的答辩状,需要在“答”与“辩”两方面下功夫,你做到了吗?

一篇出色的答辩状&#xff0c;需要在“答”与“辩”两方面下功夫&#xff0c;你做到了吗&#xff1f; 在法律诉讼中&#xff0c;答辩状的重要性不言而喻。它不仅是你回应对方指控的主要手段&#xff0c;也是展示你立场和观点的关键平台。在#李秘书讲写作#看来&#xff0c;一篇…

5.HC-05蓝牙模块

配置蓝牙模块 注意需要将蓝牙模块接5v,实测接3.3v好像不太好使的样子 首先需要把蓝牙模块通过TTL串口模块接到我们的电脑,然后打开我们的串口助手 注意,我们现在是配置蓝牙模块,所以需要进入AT模式,需要按着蓝牙模块上的黑色小按钮再上电,这时候模块上的LED灯以一秒慢闪一次…

Adobe AE(After Effects)2024下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

Python 物联网入门指南(七)

原文&#xff1a;zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第二十四章&#xff1a;基本开关 到目前为止一定是一段史诗般的旅程&#xff01;回想一下你开始阅读这本书的时候&#xff0c;你是否曾想象…

【产品介绍】安科瑞Acrel-2000T无线测温解决方案

ARTM-Pn 无线测温采集装置&#xff0c;可用于3~35kV 户内开关柜&#xff0c;包括中置柜、手车柜、固定柜、环网柜等多种开关柜&#xff0c;也可用于 0.4kV 低压柜&#xff0c;包括固定柜&#xff0c;抽屉柜等。无线温度传感器可安装于柜内任何发热点上&#xff0c;利用无线数据…

跨境物流系统解决方案:构建全球化供应链的关键步骤

随着全球化的发展&#xff0c;跨境物流已成为国际贸易中不可或缺的重要环节。然而&#xff0c;由于各国之间的政治、法律、文化和语言差异&#xff0c;跨境物流常常面临诸多挑战&#xff0c;如货物清关、运输安全、物流跟踪等问题。因此&#xff0c;构建一个高效、可靠的跨境物…

Windows如何下载Bun并在前端Vue或React项目上替代Yarn或Npm

Bun Bun网站 Bun 在 Windows 上下载并安装 Bun 非常简单。你可以使用以下命令在 Windows 10 或更高版本上安装 Bun powershell -c "irm bun.sh/install.ps1 | iex"“powershell”不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件 PowerShell 命令解决…

嵌入式第四天:(C语言入门)

目录 什么是数组&#xff1f; 数组&#xff1a; 数组的使用&#xff1a; 数组的初始化&#xff1a; 数组名&#xff1a; 数组案例&#xff1a; 一维数组的最大值&#xff1a; 一维数组的逆置&#xff1a; 数组和指针&#xff1a; 通过指针操作数组元素&#xff1a; …

UART自适应任意(典型)波特率原理以及FPGA实现

文章目录 前言一、特征值自适应原理二、整体结构框图三、接收模块四、发送模块五、编写仿真测试文件以及结果分析六、上板测试参考 前言 在上一篇文章《详解UART通信协议以及FPGA实现》我们实现了UART的通信&#xff0c;我们知道UART通信需要双方约定好波特率&#xff0c;如果想…

Hadoop大数据处理技术-配置连接篇

​2024/4/17 Hadoop学习前的准备 3&#xff09;连接虚拟机 上一节配置完成了基础的虚拟机配置及网络配置 下面我们开始建立连接 我们为什么要与虚拟机建立链接呢&#xff1f; 连接虚拟机就好像跟亲友联系一样 总得找个便捷又好用的工具才行 Secure CRT就像是一把能打开通向…

材料物理 笔记-6

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; 文…

手写spring IOC底层源码来模拟spring如何利用多级缓存解决循环依赖的问题

在文章开始之前&#xff0c;先来看一张spring IOC加载过程的脑图吧 Spring IOC的加载过程 首先,当我们去new了一个applicationContext,它底层呢就会把我们配置的bean进行扫描,然后创建成一个一个的beanDefinition放在我们的beanDefinitionMap中,此时就有了一切创造bean的原料信…

k-means聚类算法的MATLAB实现及可视化

K-means算法是一种无监督学习算法&#xff0c;主要用于数据聚类。其工作原理基于迭代优化&#xff0c;将数据点划分为K个集群&#xff0c;使得每个数据点都属于最近的集群&#xff0c;并且每个集群的中心&#xff08;质心&#xff09;是所有属于该集群的数据点的平均值。以下是…

「GO基础」文件名规范、关键字与标识符

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【数据结构与算法】最大公约数与最小公倍数

最大公因数&#xff08;英语&#xff1a;highest common factor&#xff0c;hcf&#xff09;也称最大公约数&#xff08;英语&#xff1a;greatest common divisor&#xff0c;gcd&#xff09;是数学词汇&#xff0c;指能够整除多个非零整数的最大正整数。例如8和12的最大公因数…

社交创新的标杆:解读Facebook的社交模式

引言 在当今数字化时代&#xff0c;社交媒体已成为人们日常生活和沟通的重要工具。作为全球最大的社交媒体平台&#xff0c;Facebook不仅改变了我们的社交模式&#xff0c;而且对全球的社交文化、商业活动和公共事务产生了深远的影响。本文将深入探讨Facebook的社交模式&#…