c++继承详解

embedded/2024/10/22 17:20:54/

从这篇文章开始,我们正式进入c++进阶篇章

继承的概念及定义

概念

继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有 类特性的基础上进⾏扩展

通俗来讲就是:父亲的遗产传给自己的子女,由子女去使用

增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。

这个所谓的派生类就是上面提到过的子女

继承定义

定义格式

class 派生类(子类):public  基类(父类)

                            这里的public是继承方式

{
语句;

}

继承基类(父类)成员访问方式的变化

1.基类的私有成员在派生类中无法访问。

2.基类private的成员不能在派生类中不能被直接访问,需要在派生类中定义为protected才能被访问。

3.使⽤关键字class时默认的继承⽅式是private,使⽤struct时默认的继承⽅式是public,不过最好显 ⽰的写出继承⽅式。

4.在实际运⽤中⼀般使⽤都是public继承,⼏乎很少使⽤protetced/private继承,也不提倡使⽤ protetced/private继承,因为protetced/private继承下来的成员都只能在派⽣类的类⾥⾯使⽤,实 际中扩展维护性不强。

继承中的作用域

隐藏规则

1. 在继承体系中基类和派⽣类都有独⽴的作⽤域。

2. 派⽣类和基类中有同名成员,派⽣类成员将屏蔽基类对同名成员的直接访问,这种情况叫隐藏。

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

当然啦,在实际中在继承体系⾥⾯最好不要定义同名的成员。

派生类的默认成员

4个常⻅默认成员函数

默认的成员函数就是指不需要我们去编写的函数,编译器会自动生成的成员函数

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

2. 派⽣类的拷⻉构造函数必须调⽤基类的拷⻉构造完成基类的拷⻉初始化。

3.派⽣类的operator=必须要调⽤基类的operator=完成基类的复制。但需要注意的是派生类的operator= 隐藏了基类的operator=,因此要显式调用基类的operator= 时,需要指定基类作用域

4. 派⽣类的析构函数会在被调⽤完成后⾃动调⽤基类的析构函数清理基类成员。

实现一个不能被继承的类

⽅法1:基类的构造函数私有,派⽣类的构成必须调⽤基类的构造函数,但是基类的构成函数私有化以 后,派⽣类看不⻅就不能调⽤了,那么派⽣类就⽆法实例化出对象。

方法2: :C++11新增了⼀个final关键字,final修改基类,派⽣类就不能继承了。

继承与友元

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

由此可见有缘关系不能继承

继承与静态成员

基类定义了static静态成员,则整个继承体系⾥⾯只有⼀个这样的成员。⽆论派⽣出多少个派⽣类,都 只有⼀个static成员实例。

class Person

{

public:

string _name;

static int _count;

};

int Person::_count = 0;

class Student : public Person

{

protected:

int _stuNum;

};

int main()

{

Person p;

Student s;

// 这⾥的运⾏结果可以看到⾮静态成员 _name 的地址是不⼀样的

// 说明派⽣类继承下来了,⽗派⽣类对象各有⼀份

cout << &p._name << endl;

cout << &s._name << endl;

// 这⾥的运⾏结果可以看到静态成员 _count 的地址是⼀样的

// 说明派⽣类和基类共⽤同⼀份静态成员

cout << &p._count << endl;

cout << &s._count << endl;

// 这⾥的运⾏结果可以看到⾮静态成员 _name 的地址是不⼀样的

// 说明派⽣类继承下来了,⽗派⽣类对象各有⼀份

cout << &p._name << endl;

cout << &s._name << endl;

// 这⾥的运⾏结果可以看到静态成员 _count 的地址是⼀样的

// 说明派⽣类和基类共⽤同⼀份静态成员

cout << &p._count << endl;

cout << &s._count << endl;

return 0;

}

多继承及其菱形继承问题

继承模型

单继承

单继承:⼀个派⽣类只有⼀个直接基类时称这个继承关系为单继承

举个例子

这个就是单继承

多继承

多继承:⼀个派⽣类有两个或以上直接基类时称这个继承关系为多继承

值得一提的是多继承对象在内存中的模型, 它的模型是先继承的基类在前⾯,后⾯继承的基类在后⾯,派⽣类成员在放到最后⾯

那么接下来讲一下一种特殊的继承模型

菱形继承

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

菱形继承的问题,从下⾯的对象成员模型构造,可以 看出菱形继承有数据冗余和⼆义性的问题,在Assistant的对象中Person成员会有两份。⽀持多继承就 ⼀定会有菱形继承,像Java就直接不⽀持多继承,规避掉了这⾥的问题,所以实践中我们也是不建议 设计出菱形继承这样的模型的。

虚继承

class Person

{

public:

string _name; // 姓名

/*int _tel;

int _age;

string _gender;

string _address;

*/

// ...

}; // 使⽤虚继承 Person 类

class Student : virtual public Person

{

protected:

int _num; // 学号

}; // 使⽤虚继承 Person 类

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;

}

继承和组合

public继承是一种is-a的关系,即每个派生类对象都素一个基类对象

组合是一种has-a的关系,假设b组合了a,每个b对象中都有一个a对象

都看到这里了,各位观众老爷给个三联呗,谢谢啦!!!


http://www.ppmy.cn/embedded/118403.html

相关文章

怎麼在Ubuntu上設置全局代理

在Ubuntu系統中&#xff0c;設置全局代理可以幫助用戶在整個系統範圍內應用代理配置&#xff0c;而不僅僅是某些特定的應用程式。本文將詳細介紹如何在Ubuntu上進行全局代理設置。 全局代理的好處包括但不限於&#xff1a; 統一管理&#xff1a;只需一次設置&#xff0c;全系…

Hadoop 常用生态组件

Hadoop核心组件 安装 Hadoop 时&#xff0c;通常会自动包含以下几个关键核心组件&#xff0c;特别是如果使用了完整的 Hadoop 发行版&#xff08;如 Apache Hadoop、Cloudera 或 Hortonworks 等&#xff09;。这些组件构成了 Hadoop 的核心&#xff1a; 1. HDFS&#xff08;H…

磨具生产制造9人共用一台工作站

随着技术的不断进步与工业自动化的深入发展&#xff0c;如何优化生产流程、提高设备利用率成为了众多企业面临的重大课题。那么在磨具生产制造中实现9人共用一台工作站呢&#xff1f; 一、背景与挑战 在磨具制造行业&#xff0c;高精度、高效率的生产要求与复杂多变的工艺流程…

五星级可视化页面(29):此次分享的界面,超越五星级啦

作为设计师&#xff0c;可以从超高颜值的可视化大屏界面上学习和借鉴以下几点&#xff1a; 1. 色彩运用&#xff1a; 观察颜值高的可视化大屏界面所运用的色彩搭配和调性&#xff0c;学习如何运用色彩来增强界面的视觉吸引力和信息传达效果。 2. 布局设计&#xff1a; 研究界…

『功能项目』QFrameWorkBug修改器界面【65】

我们打开上一篇64QFrameWork道具栏物品生成的项目&#xff0c; 本章要做的事情是做一个道具bug调试面板&#xff0c;可以增加主角属性&#xff0c;可以增加道具的功能 首先创建一个空物体&#xff08;钉子&#xff09; 按住Alt键将空物体钉到左侧 重命名为Left 创建Button、Im…

Spark 性能优化高频面试题及答案

目录 高频面试题及答案1. 如何通过调整内存管理来优化 Spark 性能?2. 如何通过数据持久化优化性能?3. 如何通过减少数据倾斜(Data Skew)问题来优化性能?4. 如何通过优化 Shuffle 操作提升性能?5. 如何通过广播变量(Broadcast Variables)优化性能?6. 如何通过序列化机制…

Xcode16 iOS18 编译问题适配

问题1&#xff1a;ADClient编译报错问题 报错信息 Undefined symbols for architecture arm64:"_OBJC_CLASS_$_ADClient", referenced from:in ViewController.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit co…

构建现代应用的Python Serverless架构详解

构建现代应用的Python Serverless架构详解 Serverless架构是一种新兴的计算模型&#xff0c;通过消除对底层服务器的显式管理&#xff0c;大大简化了应用的开发与运维流程。在Serverless架构中&#xff0c;开发者仅需关注代码的编写与业务逻辑的实现&#xff0c;无需考虑服务器…