C++【继承】

继承的概念

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

class Person
{
public:
void Print()
{
cout << "name:" << _name << endl;
cout << "age:" << _age << endl;
}
protected:
string _name = "peter"; // 姓名
int _age = 18; // 年龄
};
// 继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。
//这里体现出了Student复用了Person的成员。
class Student : public Person
{
protected:
int _stuid; // 学号
};int main()
{Student s;
//复用父类的函数
s.Print();return 0;
}

继承的格式

派生类+继承方式+基类

//派生类   +   继承方式  + 基类
class Student : public Person
{
protected:
int _stuid; // 学号
};

继承关系和访问限定符

继承方式:public继承,protected继承,private继承

访问限定符:public访问,protected访问,private访问

继承基类成员的访问方式的变化
类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected
成员
派生类的private
成员
基类的protected
成员
派生类的protected
成员
派生类的protected
成员
派生类的private
成员
基类的private成
在派生类中不可见在派生类中不可见在派生类中不可 见

1.基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私
有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面
都不能去访问它


2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。


3. 基类的私有成员在子类都是不可见。基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected> private。


4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。


5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承。
 

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


1.派生类对象可以赋值给基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去。(派生类中一定含有基类的内容,但基类不一定含有派生类的内容

2.基类对象不能赋值给派生类对象。

3.基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用但是必须是基类
的指针是指向派生类对象时才是安全的。

class Person
{
protected :
string _name; 
string _sex; 
int _age; 
};
class Student : public Person
{
public :
int _No ; 
};void Test ()
{
Student s;
// 1.子类对象可以赋值给父类对象/指针/引用
Person p = s;
Person* pp = &s;
Person& rp = s;//2.基类对象不能赋值给派生类对象
s = p;//错误// 3.基类的指针可以通过强制类型转换赋值给派生类的指针
pp = &s;
Student* ps1 = (Student*)pp; // 这种情况转换时可以的。
ps1->_No = 10;pp = &p;
Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以,但是会存在越界访问的问
题
ps2->_No = 10;
}

继承中的作用域
 

1. 在继承体系中基类和派生类都有独立的作用域


2. 子类和父类中有同名成员子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,
也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)


3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。


4. 注意在实际中在继承体系里面最好不要定义同名的成员。
 

此时A中的fun与B中的fun构成隐藏
注意其并不在同一作用域内,所以其并不构成重载

故测试函数运行时,会调用B类中的fun函数,隐藏A中的fun

//此时A中的fun与B中的fun构成隐藏
//注意其并不在同一作用域内,所以其并不构成重载
class A
{
public:
void fun()
{
cout << "func()" << endl;
}
};
class B : public A
{
public:
void fun(int i)
{
A::fun();
cout << "func(int i)->" <<i<<endl;
}
};
void Test()
{
B b;
b.fun(10);
};

派生类的默认成员函数
 

1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。


2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。


3. 派生类的operator=必须要调用基类的operator=完成基类的复制。


4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。


5. 派生类对象初始化先调用基类构造再调派生类构造。


6. 派生类对象析构清理先调用派生类析构再调基类的析构。


7. 在一些场景中析构函数需要构成重写,重写的条件之一是函数名相同。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。
 

继承与友元


友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
 

继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员无论派生出多少个子类,都只有一个static成员实例
 

复杂的菱形继承
 

单继承:一个子类只有一个直接父类时称这个继承关系为单继承


多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承


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

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份


如何解决菱形继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承(继承共同的基类时使用虚继承),即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。
 

class Person
{
public :
string _name ; // 姓名
};
//继承共同基类时使用virtual虚继承
class Student : virtual public Person
{
protected :
int _num ; //学号
};
//继承共同基类时使用virtual虚继承
class Teacher : virtual public Person
{
protected :
int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
string _majorCourse ; // 主修课程
};
void Test ()
{
Assistant a ;
a._name = "peter";
}

此时虚继承的内存窗口如下:

这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针(虚表),这两个表叫虚基表。虚基表中存的偏移量,通过偏移量可以找到下面的A。
 

继承和组合

1.public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。

2.组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。

3.优先使用对象组合,而不是类继承 。

4.如果要实现多态,则必须要继承,若类之间的关系可以用继承(耦合度高)也可以用组合(耦合度低,易于封装),就用组合。
 

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

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

相关文章

网上预约就医取号系统

摘 要 近年来&#xff0c;随着信息技术的发展和普及&#xff0c;我国医疗信息产业快速发展&#xff0c;各大医院陆续推出自己的信息系统来实现医疗服务的现代化转型。不可否认&#xff0c;对一些大型三级医院来说&#xff0c;其信息服务质量还是广泛被大众所认可的。这就更需要…

u盘在电脑上读不出来?这些方法或许能帮到你!

U盘作为一种便捷的存储设备&#xff0c;广泛应用于数据传输和备份。然而&#xff0c;在使用过程中&#xff0c;用户可能会遇到U盘在电脑上读不出来的问题。这种情况可能由多种原因引起&#xff0c;包括硬件故障、驱动问题、文件系统损坏等。本文将详细介绍解决u盘在电脑上读不出…

RFID技术详解

一、基本概念 概念 射频识别技术&#xff08;RFID&#xff09;又称电子标签、无线射频识别、感应电子芯片、非接触卡&#xff0c;是一种通过射频信号自动识别目标物体并获取相关数据的非接触自动识别技术。 RFID技术可以在各种恶劣的环境中工作&#xff0c;无需人为干预。 …

阿基米德签证小程序(APP)管理系统源码安装步骤说明

阿基米德所有系统支持Lunix/windows服务器环境&#xff0c;需要PHP7.1 ~ 8.3 版本支持&#xff08;推荐使用8.3&#xff09;&#xff0c; 可运行于包括Apache和nginx在内的多种WEB服务器和模式&#xff08;推荐使用nginx&#xff09;&#xff0c;支持Mysql5.0~8.0数据库&#x…

openai有什么好的框架可以用来肺结节检测

OpenAI 本身并没有专门为医学影像&#xff08;如肺结节检测&#xff09;提供特定的框架&#xff0c;但它的通用 API 和模型&#xff08;如 GPT-4 和 DALL-E&#xff09;可以与其他专门用于医学影像分析的框架结合使用&#xff0c;以实现肺结节检测。 对于肺结节检测&#xff0…

小红书点赞评论收藏【更新版本】

小红书作为社交媒体的一个亮点&#xff0c;其点赞、评论和收藏的功能形成了一种特有的交流机制。点赞简直就是一枚迷你奖章&#xff0c;为创作者带去信心与动力。一次点赞&#xff0c;表达的是你心中无言的喜好和认可&#xff1b;它如明亮的灯塔&#xff0c;在汪洋大海中为创作…

人工智能对决:ChatGLM与ChatGPT,探索发展历程

图: a robot is writing code on a horse, By 禅与计算机程序设计艺术 目录 ChatGLM:

项目实践---Windows11中安装Zookeeper3.5.5/Hadoop2.7.2/Hive2.3.7

1.背景 项目第一版本使用大数据组件核心版本均为2.x&#xff0c;需要在个人电脑搭建相关大数据环境&#xff0c;这次提供Hadoop2.7.2 Hive2.3.7版本的环境搭建。 2.相关安装包下载 链接&#xff1a;https://pan.baidu.com/s/1tkYr1UpqMKKVJHY5cfvVSw?pwddcxd 提取码&…

摊牌了,我不装了~各种Amazon Bedrock小样儿、试用装,今天免费!

探索世界顶级的大模型、智能体、文生图、对话机器人……新手&#xff1f;还是专家&#xff1f;加入我们&#xff0c;解锁精彩内容&#xff1a; l 初体验&#xff1a;在 Amazon Bedrock Playground 直接调用强大的大模型&#xff0c;点亮生成式AI技能树。 l 文生图&#xff1a…

Pyqt QCustomPlot 简介、安装与实用代码示例(二)

目录 前言实用代码示例彩色图演示散点像素图演示实时数据演示多轴演示对数轴演示 结语 所有文章除特别声明外&#xff0c;均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nixgnauhcuy’s blog&#xff01; 如需转载&#xff0c;请标明出处&#xff01; 完整代码我已经上传到…

智能自动化棋牌室小程序开发源码

开发一个智能自动化棋牌室小程序并获取其源码是一个涉及多个技术领域的复杂任务。下面是一个大致的开发流程和注意事项&#xff1a; 1. 技术选型 前端技术&#xff1a;使用微信小程序开发框架&#xff0c;如微信原生开发框架、Taro、Uni-app 等。后端技术&#xff1a;选择合适…

Class类--constructor构造函数

在JavaScript的类&#xff08;Class&#xff09;中&#xff0c;如果在 constructor&#xff08;构造函数&#xff09;里使用 ‘this.方法名()’&#xff0c;通常是用来在创建类的实例时立即调用某个方法&#xff0c;以完成一些初始化或设置操作。这种方式可以确保在对象创建时就…

建筑八大员之机械员精选试题

1.关于工程分包&#xff0c;以下说法正确的是(A)。 A.承包单位不得将其承包的全部工程肢解以后以分包的名义分别转包给他人 B.总承包单位将工程分包给不具备相应资质条件的单位 C.分包单位可以将其承包的工程再分包 D.总承包单位擅自将承包的部分工程发包给具有相应资质条件的分…

浅谈微服务架构中实现单点登录

随着微服务架构的广泛应用&#xff0c;如何在这种架构下实现单点登录&#xff08;Single Sign-On, SSO&#xff09;成为一个重要的问题。单点登录能够使用户在多个服务之间无缝访问&#xff0c;而不需要每次访问不同的服务时都重新进行身份验证。 这篇文章将详细介绍在微服务架…

工业级定制化智能硬件设备:塑造未来制造业的核心力量

在快速变化的工业环境中&#xff0c;企业面临着日益激烈的竞争和不断提高的效率需求。为了应对这些挑战&#xff0c;工业级定制化智能硬件设备成为了众多行业的首选。这类设备不仅提高了生产的灵活性和效率&#xff0c;还通过精准的数据收集和分析&#xff0c;为企业带来了前所…

鸿蒙文件操作事前准备

13900001&#xff0c;沙箱13900002 首选授权 module授权配置 "requestPermissions": [{ "name": "ohos.permission.CAMERA",}, { "name": "ohos.permission.READ_MEDIA",}, { "name": "ohos.permission.WR…

Python入门指南:从基础到高级

一、引言 1.1 Python编程语言简介 一、起源与发展 Python由荷兰计算机科学家吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;于1990年代初设计&#xff0c;作为ABC语言的一种替代品。 1991年发布了Python的第一个版本&#xff08;0.9.0&#xff09;。 2000年发布了Py…

优化MySQL并发事务:如何避免更新丢失问题?

背景描述 现在有两个事务&#xff0c;事务A和事务B&#xff0c;他们都需要修改同一行数据&#xff0c;这行数据原始值为100&#xff0c;事务A的操作是数据增加100&#xff0c;事务B的操作也是增加100&#xff0c;预期的最终结果是300&#xff0c;现在如何保证最终的数据是300的…

【C++进阶学习】第三弹——菱形继承和虚拟继承——菱形继承的二义性和数据冗余问题

继承&#xff08;上&#xff09;&#xff1a;【C进阶学习】第一弹——继承&#xff08;上&#xff09;——探索代码复用的乐趣-CSDN博客 继承&#xff08;下&#xff09;&#xff1a;【C进阶学习】第二弹——继承&#xff08;下&#xff09;——挖掘继承深处的奥秘-CSDN博客 …

教育培训系统(FastAdmin+ThinkPHP+Unipp)

引领学习新风尚 &#x1f4da; 引言&#xff1a;教育新篇章 随着科技的不断发展&#xff0c;教育形式也在不断创新与变革。教育培训系统作为这一变革的重要载体&#xff0c;正逐渐改变着我们的学习方式。今天&#xff0c;就让我们一起探索教育培训系统的魅力&#xff0c;看看它…