c++_继承

🏷如被何实现一个不能被继承的类(或是继承无意义的类)

将构造函数定义成私有的就行了,即:私有化父类的构造函数
c++ 11 新增关键字final 修饰父类直接不能被继承

class A final
{........
}

🏷继承与有元

有元关系不能被继承


🏷继承与静态成员

思考一个问题?静态成员变量可以继承吗 ?
你会发现在子类中确实可以访问静态成员变量,但是当你打印父类的静态成员变量和子类的静态成员变量的时候你会发现他们的地址是一样的。
我们可以这样来理解:首先静态成员变量它不是属于某一个对象的,它是属于整个类的。所以它这里只是相当继承了使用权,其实这里的静态成员变量的继承和成员函数的继承很像,子类继承父类的成员函数也是继承的使用权,并不是自己在单独去创建一份。


🏷复杂的菱形继承及菱形虚拟继承

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

![[Pasted image 20231121171709.png]]

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

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

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余二义性的问题
在这里插入图片描述

📌怎么分析的?

首先这个Assistant 继承了Student ,同时又继承了TeacherStudent 里面有成员变量:_age, _name, 等Teacher 里面也有成员变量:_age, _name, 等,当你想访问,Assistant时,就有两个_age 两个_name ,编译器不知道你想要的是哪个,所以就存在二义性
而且,就算你能容忍这个问题,但是所有的信息存两份会造成空间的白白浪费。

📌解决方法

为了解决菱形继承的上面两个问题,c++的祖师爷想出了一个新的办法,增加了一个新的关键字:virtual 虚继承

class Person
{
public:string _name; // 姓名
};
class Student : virtual public Person  //看在这里加上了 关键字:vitual
{
protected:int _num; //学号
};
class Teacher : virtual public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};

加上了vitual 之后,就是继承的同一份了,就避免了数据冗余的问题。

📌虚拟继承解决数据冗余和二义性的原理

一下面的代码为列:

#include<iostream>
using namespace std;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;
}
✒如何解决二义性的问题的?

我们可以通过指定类域的方法来避免这个二义性的问题:
b.B::_a = 1
b.C::_a = 2

✒如何解决数据冗余的问题的?

对象d 要存一个来自父类的成员变量_a 为了避免数据冗余,我们就不在B类和c类中存这个成员变量了,我们把_a 单独存一个地方,这样无论你使用b.B::_a = 1 还是b.c::_a = 2访问的都是一个地方,这样数据冗余的问题就解决了。

🏷继承的总结和反思

  1. 很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱

形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设

计出菱形继承。否则在复杂度及性能上都有问题。

  1. 多继承可以认为是C++的缺陷之一,很多后来的OO语言都没有多继承,如Java。

🏷继承和组合

📌什么是组合?

class C
{int _c;
};class D
{
protected:C _c;
};

上面的代码例子就是组合。
想一想:继承和组合的相同点是什么,不同点是什么?
🔎相同点:
1. 都可以复用(继承的核心是复用:子类复用父类

🔎不同点:

#include<iostream>
using namespace std;//继承
class A
{
public:void func(){}
protected:int _a;};class B: public A
{
public:void f(){           //继承的权限是比较大的除了父类的私有不可见其他的都是可以使用的func(); //父类的公有可以用_a++;     //父类的保护也可以用}
protected:	int _b;
};//组合
class C
{
public:void func(){}
protected:int _c;
};class D
{
public:void f(){_c.func(); //组合类的公有可以使用//_c._a++;   //但是组合类的保护不能使用}
protected:C _c;int _d;
};int main()
{cout << sizeof(D) << endl;cout << sizeof(B) << endl;D dd;dd.func(); //组合类的d对象不能直接调用func;B bb;bb.func(); //继承的子类B对象就能直接调用父类的func();}

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

继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称

为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的

内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很

大的影响。派生类和基类间的依赖关系很强,耦合度高。

对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象

来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复

用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。

组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被

封装。

实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有
些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用
继承,可以用组合,就用组合

📌什么时候用组合,什么时候用继承

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

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

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

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

相关文章

【springboot】idea项目启动端口被占用

问题 idea本地启动springboot项目端口老是被占用 解决 关闭被占用的端口进程 步骤: 1. winR打开程序框 2. 查出被占用端口的进程id netstat -ano | finderstr 端口号 例如 netstat -ano | finderstr 81013.杀死进程 taskkill /pid 进程id -t -f 例如 taskkill /pid 2…

vue+jsonp编写可导出html的模版,可通过外部改json动态更新页面内容

效果 导出后文件结果如图所示&#xff0c;点击Index.html即可查看页面&#xff0c;页面所有数据由report.json控制&#xff0c;修改report.json内容即可改变index.html展示内容 具体实现 1. 编写数据存储的json文件 在index.html所在的public页面新建report.json文件&#xff…

LabVIEW通过编程将图形类控件的X轴显示为时间戳

LabVIEW通过编程将图形类控件的X轴显示为时间戳 每个版本的LabVIEW中都有属性节点&#xff0c;可以以编程方式调整X轴和Y轴格式。对于不同版本的LabVIEW&#xff0c;这些属性节点无法在同一个位置找到。请参阅以下部分&#xff0c;了解特定版本LabVIEW的相关属性节点的位置。 …

GraphCast:基于机器学习的全球中期天气预测模型

文章信息 文章题为”GraphCast: Learning skillful medium-range global weather forecasting”&#xff0c;该文章于2023年发表至Science&#xff0c;文章内容主要关于利用机器学习模型&#xff0c;实现高效、准确的全球中期天气预测。由于文章内容较多&#xff0c;本文仅对研…

Typora .MD笔记中本地图片批量上传到csdn (.PNG格式)(无需其他任何图床软件)

Typora .MD笔记中本地图片批量上传到csdn &#xff08;.PNG格式&#xff09;(无需其他任何图床软件) 截图软件推荐 qq 截图 快捷键 ctrlshiftA. 步骤一 设置Typora 的图片 点击文件. 点击偏好设置 ->图像 我们可以选择将图片复制到我们的文件夹中。 建议刚写好文件标题就…

强基固本,红海云数字化重塑提升国企干部管理能力

国有企业的干部管理体系建设具有重要的战略意义&#xff0c;对于构建高素质专业化的干部队伍&#xff0c;推动企业高质量发展至关重要。特别是在党的二十大以后&#xff0c;建设中国特色现代企业制度&#xff0c;在完善公司治理中加强党的领导&#xff0c;加强党管干部党管人才…

C#图像处理OpenCV开发指南(CVStar,03)——基于.NET 6的图像处理桌面程序开发实践第一步

1 Visual Studio 2022 开发基于.NET 6的OpenCV桌面程序 1.1 为什么选择.NET 6开发桌面应用&#xff1f; 选择 .NET 6&#xff08;最早称为 .NET Core&#xff09;而非 Frameworks.NET 的理由是&#xff1a;&#xff08;1&#xff09;跨平台&#xff1b;已经支持Windows,Linux…

【数据结构】——解决topk问题

前言&#xff1a;我们前面已经学习了小堆并且也实现了小堆&#xff0c;那么我们如果要从多个数据里选出最大的几个数据该怎么办呢&#xff0c;这节课我们就来解决这个问题。我们就用建小堆的方法来解决。 首先我们来看到这个方法的时间复杂度&#xff0c;我们先取前k个数据建立…

c语言-数据在内存中的存储

文章目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断3. 浮点数在内存中的存储 1. 整数在内存中的存储 1.整数的2进制表示方法有三种&#xff0c;即 原码、反码和补码 2. 三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用0表示“正”&#xff0c;用1表示“…

Offer来了:Java面试核心知识点精讲

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 送书第四期 《AI时代项目经理成长之道》 …

vue3 setup语法糖,常用的几个:defineProps、defineEmits、defineExpose、

vue3和vue2组件之间传参的不同 <script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。 <script setup> 中的代码会在每次组件实例被创建的时候执行。 任何在 <script setup> 声明的顶层的绑定 (包括变量&#xff0c;函数声明&#xff0…

网站公安备案流程

1.公安备案网址 https://beian.mps.gov.cn/ 选择用户登录->法人用户登录 左边的码下载APP&#xff0c;登上去之后用APP扫右边的码&#xff0c;人脸识别