C++语法(15)---- 继承

news2024/11/19 18:34:03

C++语法(14)---- 模板进阶_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130092939?spm=1001.2014.3001.5501

目录

1.继承概念和定义

1.概念

2.定义 

1.格式

2. 继承关系和访问限定符

2.基类和派生类对象赋值转换

3.继承中的作用域

针对成员对象

针对成员函数

注意

4.派生类的默认成员函数

默认生成的四个成员函数

派生类默认成员函数

1.构造函数

2.拷贝构造

3.赋值拷贝

4.析构函数

5.继承与友元

6.继承与静态成员

7.多继承

单继承形式

多继承形式

菱形继承

虚拟继承解决数据冗余/二义性问题

虚拟继承的原理

1.菱形继承存储模式

1.菱形虚拟继承存储模式

8.组合和继承辨析


1.继承概念和定义

1.概念

1.一个函数调用另有一个函数,那么重要直接写出其函数满足的要求即可,函数就被复用了

2.类中是不是也可以像函数那样复用呢,此时就有了继承的概念。

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

以前我们接触的复用都是函数复用,继承是类设计层次的复用。

2.定义 

class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter"; // 姓名
	int _age = 18; // 年龄
};

class Student : public Person
{
protected:
	int _stuid; // 学号
};

class Teacher : public Person
{
protected:
	int _jobid; // 工号
};

int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

1.格式

下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类

2. 继承关系和访问限定符

1.基类private:基类自己可以访问;继承到派生类里,派生类不可见private

2.权限:public > protect,派生类继承方式和基类的成员权限取小的权限

3.访问限定符前的" : "可以不写,class的默认是私有,struct默认是公有


4. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡
使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里
面使用,实际中扩展维护性不强

2.基类和派生类对象赋值转换

1.在public继承中,派生类可以直接转换为基类,不需要进行类型转换 -- 也就意味着中间不存在类型转换

2.引用的相关内容

①因为派生类转基类没有类型转换,那么可直接引用,引用的内容是派生类中基类的部分

②非继承关系的普通类型,其赋值其实是需要中间的临时变量进行转换,但是引用指向了临时变量,临时变量具有常性,所以编译器报错;固想要赋值正常,需要在前面加const修饰

 3.指针

 4.总结

即继承可以向上直接转换,前提是基类的成员是公有成员

3.继承中的作用域

针对成员对象

1. 在继承体系中基类和派生类都有独立的作用域,所以能两个结构体取同一个名字
2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,若想使用,基类的同名变量,只要 基类::基类成员 显示访问就可以了)

针对成员函数

如果是成员函数的隐藏,只需要函数名相同就构成隐藏

注意

1.在实际中在继承体系里面最好不要定义同名的成员
2.重载需要在同一个作用域

3.重定义是继承时,派生类和基类有同名函数,构成函数名隐藏

4.派生类的默认成员函数

默认生成的四个成员函数

1.针对构造函数和析构函数

内置类型不处理,使得我们需要对内置类型手动处理

自定义类型调用对应的构造和析构

一般析构自动生成就够用了,特别的需要针对逐项释放可以自己写

2.针对拷贝构造和赋值拷贝

内置类型浅拷贝

自定义类型调用对应的拷贝构造和赋值拷贝

至于什么时候需要自己写,那就是需要深拷贝的情况,那么一个标志就是析构要自己写

派生类默认成员函数

1.构造函数

1.派生类不显示写会默认调用基类的默认构造

2.如果要主动构造,需要调用基类的构造函数,而不能直接定义基类的成员变量

3.先调用基类的构造函数,再调用派生类的构造函数

2.拷贝构造

1.派生类不显示写会默认调用基类的拷贝构造

2.如果要主动拷贝构造,需要调用基类的拷贝构造,而不能直接定义基类的成员变量

3.另外针对主动拷贝构造,基类要传入基类,不过由于派生类可以切割变成基类,所以不需要转换

3.赋值拷贝

1.派生类不显示写会默认调用基类的赋值拷贝

2.如果要主动拷贝构造,需要调用基类的赋值拷贝,而不能直接定义基类的成员变量

3.由于其operator=派生类和基类同名,构成隐藏,如果不指定基类显示调用,会出现死递归随后栈溢出;所以赋值拷贝调用基类需要显示调用operator=()函数

4.析构函数

1.派生类不显示写会默认调用基类的析构函数

2.手动调用,要加作用域修饰基类析构函数

3.之所以要加作用域,因为派生类的析构和基类的构造函数构成隐藏关系(由于多态关系需求,所有析构函数都会特殊处理成统一的destructor()函数名,由此构成隐藏关系)

4.主动写析构函数,会调用多次析构函数,可能会有危险,因此不需要显示写析构函数

5.派生类析构完成再析构基类的析构

5.继承与友元

###友元不会被继承

6.继承与静态成员

class Person
{
protected:
	string _name; // 姓名
public:
	static int _count; // 统计人的个数。
};
int Person::_count = 0;

class Student : public Person
{
protected:
	int _stuNum; // 学号
};

int main()
{
	Person p;
	Student s;
	p._count++;
	s._count++;
	cout << Person::_count << endl;
	Student::_count = 0;
	cout << Student::_count << endl;
}

基类的静态成员和派生类继承的静态成员是同一个

特殊的:

class Person
{
public:
	string _name; // 姓名
	void Print()
	{
		cout << 0 << endl;
	}
public:
	static int _count; // 统计人的个数。
};
int Person::_count = 0;

int main()
{
	Person* pp = nullptr;
	cout << pp->_count << endl; //可以运行
    cout <<(*PP)._count<< endl; //会优化,与上面一样

	pp->Print();                //可以运行
    (*PP)->Print();             //会优化,与上面一样

    cout << pp->_name<< endl;   //不可以运行
}

函数并没有在类型中,函数在代码段中

静态变量没有存在类中,而在静态区

而类中的变量,由于指针是空,无法访问到

7.多继承

单继承形式

多继承形式

多继承本身没什么问题,但是多继承后可能会生成菱形继承,这样就有数据冗余和二义性的问题。

菱形继承

在空间角度:数据冗余

在逻辑角度:二义性

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";
}

当然,能都指定哪个类的数据命名解决二义性的问题,但是数据依然冗余

虚拟继承解决数据冗余/二义性问题

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。关键之 --- virtual

在腰部使用virtual进行虚拟继承

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; // 主修课程
};

问题解决,三个东西其实是同一个的

虚拟继承的原理

1.菱形继承存储模式

class A
{
public:
	int _a;
};

class B : public A
{
public:
	int _b;
};

class C : public A
{
public:
	int _c;
};

class D : public B, public C
{
public:
	int _d;
};

菱形继承模型

1.菱形虚拟继承存储模式

class A
{
public:
	int _a;
};

class B :virtual public A
{
public:
	int _b;
};

class C :virtual public A
{
public:
	int _c;
};

class D : public B, public C
{
public:
	int _d;
};

那么B,C的开头又是什么?

这些其实是指针,它指向一虚基表,该虚基表的第二个数据值存储了偏移量

为了让B和C找到A,使得B,C,D的_a都是一个共同的数据;

访问A的内容比较麻烦,访问B的数据比较方便;

如果切牌你,形式其实依然是先有一个指针,随后跟着数据;只是偏移量变小了

这样设计如果A的大小足够大,那就节省了空间,因为由指针替换了整体。

8.组合和继承辨析

//继承
class X
{
public:
	int _x;
};

class Y:public X
{
public:
	int _y;
};

//组合
class M
{
public:
	int _m;
};

class N
{
	M m;
	int _n;
};

1.继承和组合都完成了复用

2.protect能继承下来;继承为白箱复用(看得见内部),组合为黑箱复用(不知道内部)

3.继承更多逻辑关系是is-a;组合是一种has-a的关系

4.如果都能用,选择组合,组合更满足低耦合(依赖性不高)

耦合的解释:假设100个成员,80个保护,20个公有

继承:由于关联度很强,任何一个修改都会影响到派生类,因为保护的也被继承了,派生类看待基类是信息透明的(白箱)

组合:该类只有20个公有修改才可能影响到组合的,组合看待类的内容是不完全公开的(黑箱)

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

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

相关文章

ERTEC200P-2 PROFINET设备完全开发手册(5-2)

5.2 TIA 数据记录操作 在PLC的程序中&#xff0c;可以通过指令RDREC和WRREC读写数据记录&#xff0c;在参考代码里可以看到读写操作都实现了index 2的记录数据&#xff0c;并且初始化为&#xff1a; #define DEMO_RECORD "ABCDEFGH" 首先定义要写入和读出的数据…

【LeetCode】剑指 Offer(26)

目录 题目&#xff1a;剑指 Offer 51. 数组中的逆序对 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 51. 数组中…

数据库MySQL —— 锁

目录 一、概述 二、全局锁 三、表级锁 1. 表锁 2. 元数据锁 3. 意向锁 四、行级锁 1. 行锁 2. 间隙锁 / 临键锁 一、概述 锁 是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O)的争用以外&…

channel 源码解析(5问)

目录 1.channel底层数据结构是什么 2.channel创建的底层实现 3.channel 的发送过程 4.channel的接受过程 5.关闭 channel 1.channel底层数据结构是什么 channel底层的数据结构是hchan,包括一个循环链表和2个双向链表 type hchan struct {qcount uint // tota…

Linux命令·route

Linux系统的route命令用于显示和操作IP路由表&#xff08;show / manipulate the IP routing table&#xff09;。要实现两个不同的子网之间的通信&#xff0c;需要一台连接两个网络的路由器&#xff0c;或者同时位于两个网络的网关来实现。在Linux系统中&#xff0c;设置路由通…

BGP小型实验

实验分析 1.主要考察的是对BGP配置的熟练 2.实验需要在R1与R5分别发布一条路由可以在BGP 中使用network 网段 掩码命令 3.R1与R2,R4与R5是EBGP&#xff0c;而R2,R3,R4是IBGP 实验操作 1.配置接口ip,与环回路由 以R1为例 2.AS内部需要实现非直连的建立是需要保证IBGP内部是通的所…

网络编程之IP协议

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

ChatGPT 存在很大的隐私问题

当 OpenAI 发布时 2020 年 7 月的 GPT-3&#xff0c;它提供了用于训练大型语言模型的数据的一瞥。 根据一篇技术论文&#xff0c;从网络、帖子、书籍等中收集的数百万页被用于创建生成文本系统。 在此数据中收集的是您在网上分享的一些关于您自己的个人信息,这些数据现在让 O…

YGG 代表 Web3 Gaming 参加 2023 年游戏开发者大会

Yield Guild Games&#xff08;YGG&#xff09;在 2023 年 3 月 20 日至 24 日在加州旧金山举行的游戏开发者大会&#xff08;GDC&#xff09;上大显身手&#xff0c;这是游戏开发者的重要交流学习活动。虽然 GDC 本身提供了多种多样的活动&#xff0c;包括讲座、小组讨论、圆桌…

基于html+css的盒子展示6

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

无公网IP?教你在外远程访问本地wamp服务器「内网穿透」

目录 前言 1.Wamp服务器搭建 1.1 Wamp下载和安装 1.2 Wamp网页测试 2. Cpolar内网穿透的安装和注册 2.1 本地网页发布 2.2 Cpolar云端设置 2.3 Cpolar本地设置 3. 公网访问测试 4. 结语 前言 软件技术的发展日新月异&#xff0c;各种能方便我们生活、工作和娱乐的新…

OA系统的功能和作用是什么(OA系统百科)

OA系统的功能和作用是什么&#xff08;OA系统百科&#xff09;。OA系统是一种非常实用的企业内部管理系统&#xff0c;它可以帮助公司实现各项管理工作&#xff0c;可以说是整个公司和团队的纽带&#xff0c;有助于提高工作效率和管理水平。 具体来说&#xff0c;OA系统的作用…

Linux运维进阶之路

前言 首先在我看来&#xff0c;不论你以后是做运维亦或者是做后端开发&#xff0c;云计算等。只要和后端搭边&#xff0c;Linux都是必会的基础知识。所以说Linux是伴随我们工作中一个特别重要的知识。 不过很多同学在初学Linux的时候&#xff0c;始终不得其法&#xff0c;发现…

科技赋能文旅:蓝海创意云携手苏州乐园打造“元宇宙灯会”

4月8日&#xff0c;苏州乐园“欢乐寻梦季”元宇宙灯会即将正式亮灯&#xff0c;这是一场以元宇宙技术为核心&#xff0c;结合现代灯展、数字科技、潮玩游乐等元素&#xff0c;打造的一场大型的沉浸式数字光影体验。 蓝海创意云作为苏州高新区元宇宙龙头企业&#xff0c;以多年…

量化择时——SVM机器学习量化择时(第1部分—因子测算)

文章目录机器学习在量化模型上的应用机器学习量化应用场景量化模型有效性的思考机器学习模型在量化择时中的应用训练与预测流程训练数据特征构造SVM模型与测算SVM训练与预测效果测算效果分析最近ChatGPT比较火&#xff0c;NLP的同学们感触肯定会更深。NLP的应用为人所知并积极部…

【电子学会】2022年12月图形化一级 -- 潜水

潜水 暑假小雨和爸爸去玩了潜水,他见到了各种各样的海洋生物。 1. 准备工作 (1)添加背景“Underwater 2”; (2)删除小猫角色,添加角色“Diver2”、“Fish”、“Jellyfish”、“Shark”; (3)为背景添加声音“Xylo2”。 2. 功能实现 (1)点击绿旗,播放背景音乐…

【chatGPT】chatGPT初步体验,赶快来学习吧

目录 1、什么是ChatGPT 2、我可以相信人工智能告诉我真相吗&#xff1f; 3、你会使用我的对话进行培训吗&#xff1f; 4、ChatGPT 接口参考 认证 请求组织 5、ChatGPT初体验 1、什么是ChatGPT ChatGPT的研究预览是免费使用的。 ChatGPT 是从 GPT-3.5 微调而来的&#x…

vue3+typescript+vant页面开发案例

文章目录效果index.vue页面template内容script内容index.ts页面效果 index.vue页面 template内容 <van-form submit"onSubmit"><van-cell-group inset><van-fieldv-model"providerApply.companyName"name"企业名称"label"企…

snipaste 截图工具——可以使图片悬浮在任何软件上,方便对比

一、下载 官网下载地址&#xff1a;Snipaste Downloads &#xff08;需要梯子&#xff09; CSDN下载地址&#xff1a;https://download.csdn.net/download/weixin_43042683/87671809 1. 下载 压缩包后&#xff0c;免安装&#xff0c;直接解压后既可以使用。 2. 点击Snipaste.…

【c语言】二维数组与指针 存储原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…