菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍

文章目录

  • 前言
  • 一、菱形继承的类对父类的初始化
  • 二、组合
  • 三、 多态
    • 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. 构成多态

构成多态需要两个条件:

  1. 必须通过基类的指针或者引用调用虚函数
  2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
// 构成多态
#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可以实现多态,保证指向的对象正确调用析构函数。

析构函数可以构成虚函数重写吗, 为什么要构成虚函数重写?

  1. 析构函数加virtual会构成析构函数,因为编译器会将析构函数的名字统一命名为destructor
  2. 构成虚函数重写是因为,我们new一个派生类对象的空间,但是用基类的类型指针接收
  3. 在析构这个对象时,只会进行普通调用,普通调用会按照当前类型, 则只会调用基类的析构函数
  4. 这种情况,我们希望是一个多态调用,按照指向的类型调用析构函数,就需要构成虚函数的重写。
#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;
}

在这里插入图片描述


总结

菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍

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

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

相关文章

YOLOv8——测量高速公路上汽车的速度

引言 在人工神经网络和计算机视觉领域&#xff0c;目标识别和跟踪是非常重要的技术&#xff0c;它们可以应用于无数的项目中&#xff0c;其中许多可能不是很明显&#xff0c;比如使用这些算法来测量距离或对象的速度。 测量汽车速度基本步骤如下&#xff1a; 视频采集&#x…

JVM的基本组成

一、JDK\JRE\JVM JDK: 全称 "Java Development Kit" &#xff0c;Java 开发工具包&#xff0c;提供 javac 编译器、jheap、jconsole 等监控工具;JRE: 全称"Java Runtime Environment"&#xff0c;Java 运行环境&#xff0c;提供Class Library 核心类库 JV…

同等学力英语用什么app背单词

同等学力申硕的意义和作用 授予同等学力人员硕士学位是国家为同等学力人员开辟的获得学位的渠道&#xff0c;对于在职人员业务素质的提高和干部队伍建设起到积极作用。它为那些没有传统学历背景但具有相应学术水平的人员提供了获取学位的机会&#xff0c;有助于提升他们的职业竞…

WebSocket实现在线聊天室

项目实现源码&#xff1a; 前端源码 后端源码 1.常见的消息推送方式 1.1 轮询 1.1.1 轮询的概念 客户端以固定的事件间隔&#xff08;例如每秒或几分钟&#xff09;向服务器发送HTTP请求&#xff0c;服务器收到请求后&#xff0c;处理请求并返回数据给客户端 轮询具体实现htt…

POI获取模板文件,替换数据横纵动态表格、折线图、饼状图、折线饼状组合图

先说几个关键的点 pom.xml依赖 <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version> </dependency> <dependency><groupId>com.deepoove</groupId>&…

鸭脖变“刺客”,啃不起了

撰文&#xff5c;ANGELICA 编辑&#xff5c;ANGELICA 审核&#xff5c;烨 Lydia 声明&#xff5c;图片来源网络。日晞研究所原创文章&#xff0c;如需转载请留言申请开白。 你有多久没吃卤味了&#xff1f; 2020年之后&#xff0c;人们对于几大卤味巨头的关注度正在下降。 …

【MySQL 04】数据类型

目录 1.数据类型分类 2.数值类型 2.1 tinyint 类型 2.2 bit类型 2.3 float类型 2.4decimal 3.字符串类型 3.1 char类型 3.2 varchar类型 4.日期和时间类型 6. enum和set类型 6.1.enum和set类型简介&#xff1a; 6.2.enum和set的一般使用方法 6.3.用数字的方式…

业务数据批量插入数据库实践

业务数据如何存储一直以来都是项目开发中的一个比较重要的话题。我们要从资源的利用率&#xff0c;业务场景和技术实现多个方面考虑存储的问题。“抛开业务谈技术就是耍流氓”&#xff0c;所有技术架构都要站在实际的业务场景中分析。比如个人端的产品&#xff0c;这种就属于读…

fiddler抓包11_列表显示服务器IP (配置文件)

请求列表默认不显示服务器IP字段&#xff0c;也无法从定制列窗口添加&#xff0c;可以修改CustomRules.js实现。 ① 菜单栏“Rules”&#xff08;规则&#xff09; - “Customize Rules...”&#xff08;自定义规则&#xff09;&#xff0c;打开CustomRules.js文件。 &#xf…

基于stm32的跑步机控制系统设计-设计说明书

设计摘要&#xff1a; 随着人们对健康和健身的关注增加&#xff0c;跑步机逐渐成为室内健身的主要设备之一。本文提出了一种基于STM32的跑步机控制系统设计&#xff0c;旨在实现对跑步机的运行速度、倾斜角度和运动模式等参数的精确控制&#xff0c;提供更好的健身体验。 首先…

vue3开发中易遗漏的常见知识点

文章目录 组件样式的特性Scoped CSS之局部样式的泄露Scoped CSS之深度选择器CSS Modules在CSS中使用v-bind 非props属性继承组件通信父子组件的相互通信props/$emit父组件传递数据给子组件子组件传递数据给父组件 非父子组件的相互通信Provide/inject全局事件总线 组件插槽作用…

LVGL 控件之消息框(lv_msgbox)

目录 一、概述二、消息框1、创建消息框2、获取消息框的组成部分3、关闭消息框部件4、消息框部件事件5、API 函数 一、概述 消息框部件是由多个小部件构建而成的&#xff0c;包括&#xff1a;lv_obj、lv_btn、lv_label 和 lv_btnmatrix 部件&#xff0c;示意图如下所示&#xf…

简单题83. 删除排序链表中的重复元素 (Java)20240920

问题描述&#xff1a; java&#xff1a; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; th…

【LLM学习之路】9月23日24日 第十、十一天 Attention代码解读

【LLM学习之路】9月23日24日 第十、十一天 Attention代码解读 Transformer模型大致分为三类 纯 Encoder 模型&#xff08;例如 BERT&#xff09;&#xff0c;又称自编码 (auto-encoding) Transformer 模型&#xff1b;纯 Decoder 模型&#xff08;例如 GPT&#xff09;&#…

基于python的django微博内容网络分析系统,实现文本划分词结构

本项目旨在开发一个基于Python的Django框架的微博内容网络分析系统&#xff0c;聚焦于微博文本的分词处理、名词提取和主成分分析。该系统通过数据收集与预处理、分词及结构化文本分析&#xff0c;为舆情监测、话题分析和用户行为研究提供了一体化的解决方案。 主要功能包括&a…

lkhgjfjghkbhjk

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

LED驱动电路

LED驱动电路简介 摘要&#xff1a; LED照明是今年来快速兴起发展的一种新型光源&#xff0c;它的许多良好特点使得它的应用面越来越广。LED的单向导电特性使人一般认为应该用直流驱动&#xff0c;但是对直流恒压和限流的装置在保证比较好的限流特性时&#xff0c;自身功耗是很…

路政通 | OPENAIGC开发者大赛高校组AI创新之星奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

深圳某局联想SR850服务器黄灯 不开机维修

深圳 福田区1台Lenovo Thinksystem SR850 四路服务器黄灯问题现场处理。 1&#xff1a;型号&#xff1a;联想SR850 机架式2U服务器 2&#xff1a;故障&#xff1a;能通电&#xff0c;开机按钮快闪&#xff0c;随后叹号警告灯常亮 3&#xff1a;用户自行折腾无果后找到我们tech …