菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍
文章目录
- 前言
- 一、菱形继承的类对父类的初始化
- 二、组合
- 三、 多态
- 1. 构成多态
- 2. 虚函数
- 3. 虚函数的重写
- 4. 虚函数重写的两个例外
- 1. 协变
- 2. 析构函数的重写
- 5. C++11 final 和 override
- 1. final
- 2. override
- 6. 设计不想被继承的类
- 7. 重载、覆盖(重写)、 隐藏(重定义)的对比
- 四、多态的原理
- 总结
前言
菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍
一、菱形继承的类对父类的初始化
#include<iostream>
#include <string>
using namespace std;class A
{
public:A(const char* A):_a(A){cout << "class A" << endl;}string _a;
};class B : virtual public A
{
public:B(const char* A, const char* B):A(A),_b(B){cout << "class B" << endl;}string _b;
};class C : virtual public A
{
public:C(const char* A, const char* C):A(A),_c(C){cout << "class C" << endl;}string _c;
};class D : public B, public C
{
public:D(const char* A, const char* B, const char* C, const char* D): A(A), B(A, B), C(A, C), _d(D){cout << "class D" << endl;}string _d;
};int main()
{D d("class A", "class B", "class C", "class D");return 0;
}
结构为:
- 因为D类有如上的结构,所以A类会在D类中调用构造函数初始化,并且只调用一次,在D类中初始化B类和C类时,传入的A类不调用A类的构造函数初始化。
二、组合
- public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
- 组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
优先使用对象组合,而不是类继承。
#include <iostream>
using namespace std;class A
{
protected:int _a;
};class B : public A
{
protected:A _bb;
};int main()
{return 0;
}
三、 多态
1. 构成多态
构成多态需要两个条件:
- 必须通过基类的指针或者引用调用虚函数
- 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
// 构成多态
#include<iostream>
using namespace std;class Person
{
public:virtual void BuyTicket(){cout << "购票---全价" << endl;}
};class Student : public Person
{
public:virtual void BuyTicket(){cout << "购票---半价" << endl;}
};//void fun(Person& p)
//{
// p.BuyTicket();
//}void fun(Person* p)
{p->BuyTicket();
}int main()
{Person p;fun(&p);Student s;fun(&s);return 0;
}
2. 虚函数
虚函数:即被virtual修饰的类成员函数称为虚函数。
class Person
{
public:virtual void BuyTicket(){cout << "购票---全价" << endl;}
};
3. 虚函数的重写
虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。
在重写基类的虚函数的时候,虽然派生类的虚函数不写virtual也可以构成重写, 但是不建议这样使用
#include<iostream>
using namespace std;class Person
{
public:virtual void BuyTicket(){cout << "购票---全价" << endl;}
};class Student : public Person
{
public:virtual void BuyTicket(){cout << "购票---半价" << endl;}
};
4. 虚函数重写的两个例外
1. 协变
基类与派生类虚函数返回值类型不同。
简单来讲就是 基类与派生类的虚函数的返回值构成父子类指针或引用关系。
#include <iostream>
using namespace std;class A {};
class B :public A {};class Person
{
public:virtual A* BuyTicket(){cout << "购票---全价" << endl;return new A;}
};class Student : public Person
{
public:virtual B* BuyTicket(){cout << "购票---半价" << endl;return new B;}
};void fun(Person& p)
{p.BuyTicket();
}int main()
{Person p;fun(p);Student s;fun(s);return 0;
}
- 基类和派生类构成父子类指针的关系
2. 析构函数的重写
虽然基类和派生类的析构函数的函数名不同,但是编译器会将析构函数的函数名,都处理成destructor,因此可以构成重写。
一般情况下,应该将派生类的析构函数与基类析构函数构成函数重写,使下面的情况delete可以实现多态,保证指向的对象正确调用析构函数。
析构函数可以构成虚函数重写吗, 为什么要构成虚函数重写?
- 析构函数加virtual会构成析构函数,因为编译器会将析构函数的名字统一命名为destructor
- 构成虚函数重写是因为,我们new一个派生类对象的空间,但是用基类的类型指针接收
- 在析构这个对象时,只会进行普通调用,普通调用会按照当前类型, 则只会调用基类的析构函数
- 这种情况,我们希望是一个多态调用,按照指向的类型调用析构函数,就需要构成虚函数的重写。
#include <iostream>
using namespace std;class Person
{
public:virtual void BuyTicket(){cout << "购票---全价" << endl;}virtual ~Person(){cout << " ~Person() " << endl;}
};class Student : public Person
{
public:virtual void BuyTicket(){cout << "购票---半价" << endl;}virtual ~Student(){cout << " ~Student() " << endl;}
};int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2; // p2->destuctor() + operator delete(p)// 这里我们期望是一个多态调用,而不是普通调用p1 = nullptr;p2 = nullptr;return 0;
}
5. C++11 final 和 override
1. final
final 修饰的虚函数不能被重写
final修饰的类,不能被当做基类, 不能被继承
2. override
检查派生类中的虚函数与基类中虚函数是否构成重写,若不构成重写则报错。
#include <iostream>
using namespace std;class Person
{
public:virtual void BuyTicket(){}};class Student : public Person
{
public:// 检查派生类中的虚函数与基类中的虚函数是否构成重写virtual void BuyTicket()override{cout << "购票---半价" << endl;}
};int main()
{Person p;return 0;
}
6. 设计不想被继承的类
将构造函数私有或者将析构函数私有
将构造函数私有
#include <iostream>
using namespace std;class A
{
public:static A CreateObj(){return A();}
private:A() {}};int main()
{A::CreateObj();return 0;
}
7. 重载、覆盖(重写)、 隐藏(重定义)的对比
四、多态的原理
普通调用在编译时地址就确定了
多态调用在程序运行时,到指向对象的虚函数表中找函数的地址
#include <iostream>
using namespace std;class Person
{
public:virtual void BuyTicket(){cout << "购票---全价" << endl;}int _a = 0;};class Student: public Person
{
public:virtual void BuyTicket(){cout << "购票---半价" << endl;}int _b = 1;
};// 普通调用
//void fun(Person p)
//{
// p.BuyTicket();
//}// 多态调用
void fun(Person& p)
{p.BuyTicket();
}int main()
{Person p;Student s;return 0;
}
总结
菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍
相关文章:

菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍
文章目录 前言一、菱形继承的类对父类的初始化二、组合三、 多态1. 构成多态2. 虚函数3. 虚函数的重写4. 虚函数重写的两个例外1. 协变2. 析构函数的重写 5. C11 final 和 override1. final2. override 6. 设计不想被继承的类7. 重载、覆盖(重写)、 隐藏…...
React Native 在 build 的时候如果出现 `babel.config.js` 配置文件的错误
React Native 在 build 的时候如果出现以下错误, 就是 babel.config.js 配置文件的错误. Showing Recent Issues node:internal/process/promises:289triggerUncaughtException(err, true /* fromPromise */);^Error: .plugins[0][1] must be an object, false, or undefineda…...

【Linux】包管理器、vim详解及简单配置
🚀个人主页:小羊 🚀所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、包管理器1.1 apt1.2 yum 二、Linux编辑器——vim2.1 vim的三种模式2.2 vim普通模式常用命令2.2.1 移动…...

AVL树实现
1.AVL的概念 1.AVL树属于二叉搜索树的一种,但它不同与普通的二叉搜索树还具有以下的性质: 每一个根的左右子树的高度差的绝对值不超过1。AVL树是通过高度差去控制平衡的,所以又称作为平衡二叉搜索树。 2.AVL树实现我们引入了一个平衡因子的概…...

初始MYSQL数据库(6)—— 事务
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: MYSQL 目录 事务的概念 事务的ACID特性 使用事务 查看支持事务的存储引擎 事务的语法 保存点 自动/手动提交事务 事务的隔离性和…...

0基础学习PyTorch——GPU上训练和推理
大纲 创建设备训练推理总结 在《Windows Subsystem for Linux——支持cuda能力》一文中,我们让开发环境支持cuda能力。现在我们要基于《0基础学习PyTorch——时尚分类(Fashion MNIST)训练和推理》,将代码修改成支持cuda的训练和推…...

这款免费工具让你的电脑焕然一新,专业人士都在用
HiBit Uninstaller 采用单一可执行文件的形式,无需复杂的安装过程,用户可以即刻开始使用。这种便捷性使其成为临时使用或紧急情况下的理想选择。尽管体积小巧,但其功能却异常强大,几乎不会对系统性能造成任何负面影响。 这款工具的一大亮点是其多样化的功能。它不仅能够常规卸…...
Java高级Day52-BasicDAO
138.BasicDao 基本说明: DAO:data access object 数据访问对象 这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作 在BasicDao 基础上,实现一张表对应一个Dao,…...
【OceanBase 诊断调优】—— SQL 诊断宝典
视频 OceanBase 数据库 SQL 诊断和优化:https://www.oceanbase.com/video/5900015OB Cloud 云数据库 SQL 诊断与调优的应用实践:https://www.oceanbase.com/video/9000971SQL 优化:https://www.oceanbase.com/video/9000889阅读和管理SQL执行…...

微服务Redis解析部署使用全流程
目录 1、什么是Redis 2、Redis的作用 3、Redis常用的五种基本类型(重要知识点) 4、安装redis 4.1、查询镜像文件【省略】 4.2、拉取镜像文件 4.3、启动redis并设置密码 4.3.1、修改redis密码【可以不修改】 4.3.2、删除密码【坚决不推荐】 5、S…...

C++之STL—常用排序算法
sort (iterator beg, iterator end, _Pred) // 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置 // beg 开始迭代器 // end 结束迭代器 // _Pred 谓词 random_shuffle(iterator beg, iterator end); // 指定范围内的元素随机调…...
【驱动】地平线X3派:备份与恢复SD卡镜像
1、备份镜像 1.1 安装gparted GParted是硬盘分区软件GNU Parted的GTK+图形界面前端,是GNOME桌面环境的默认分区软件。 GParted可以用于创建、删除、移动分区,调整分区大小,检查、复制分区等操作。可以用于调整分区以安装新操作系统、备份特定分区到另一块硬盘等。 在Ubun…...

【C++报错已解决】std::ios_base::failure
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...
matlab入门学习(四)多项式、符号函数、数据统计
一、多项式 %多项式(polynomial)%创建 p[1,2,3,4] %系数向量,按x降幂排列,最右边是常数(x的0次幂) f1poly2str(p,x) %系数向量->好看的字符串 f x^3 2 x^2 3 x 4(不能运算的式子…...
leetcode621. 任务调度器
给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表,用字母 A 到 Z 表示,以及一个冷却时间 n。每个周期或时间间隔允许完成一项任务。任务可以按任何顺序完成,但有一个限制:两个 相同种类 的任务之间必须有长度为 n 的冷却时…...
Spark 的 Skew Join 详解
Skew Join 是 Spark 中为了解决数据倾斜问题而设计的一种优化机制。数据倾斜是指在分布式计算中,由于某些 key 具有大量数据,而其他 key 数据较少,导致某些分区的数据量特别大,造成计算负载不均衡。数据倾斜会导致个别节点出现性能…...

讯飞星火编排创建智能体学习(一)最简单的智能体构建
目录 开篇 智能体的概念 编排创建智能体 创建第一个智能体 编辑 大模型节点 测试与调试 开篇 前段时间在华为全联接大会上看到讯飞星火企业级智能体平台的演示,对于拖放的可视化设计非常喜欢,刚开始以为是企业用户才有的,回来之后查…...
mac-m1安装nvm,docker,miniconda
1.安装minicondaMAC OS(M1)安装配置miniconda_mac-mini m1 conda-CSDN博客 2.安装nvm(用第二个方法)Mac电脑安装nvm(node包版本管理工具)-CSDN博客 3.安装docker dmg下载链接docker-toolbox-mac-docker-for-mac安装包下载_开源镜像站-阿里云 教程MacOS系…...

STM32F407之Flash
寄存器分类 一般寄存器分为只读存储器 (ROM) 随机存储器(RAM) 只读存储器 只读存储器也被称为ROM 在正常工作时只能读不能写。 只读存储器经历的阶段 ROM->PROM->EPROM->EEPROM ->Flash 优点:掉电不丢失,解构简单 缺点:只适…...

优化 Go 语言数据打包:性能基准测试与分析
场景:在局域网内,需要将多个机器网卡上抓到的数据包同步到一个机器上。 原有方案:tcpdump -w 写入文件,然后定时调用 rsync 进行同步。 改造方案:使用 Go 重写这个抓包逻辑及同步逻辑,直接将抓到的包通过网…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...