C++ Day6

目录

一、菱形继承

1.1 概念

1.2 格式

二、虚继承

2.1 作用

2.2 格式

2.3注意

三、多态

3.1函数重写

3.2 虚函数

3.3 赋值兼容规则

3.4 多态中,函数重写的原理

3.5 虚析构函数

3.5.1 格式

3.6 纯虚函数

3.6.1格式

四、抽象类

五、模板

5.1模板的特点

5.2 函数模板

5.2.1作用

5.2.2 格式

 六、练习

1.定义一个基类 Animal,其中有一个虚函数 perform(),用于在子类中实现不同的表演行为。

 结果为:

2.用函数模板实现不同数据类型的交换功能。

结果为:


一、菱形继承

1.1 概念

菱形继承又称为钻石继承,由公共基类派生出多个中间子类,又由多个中间子类共同派生出汇聚子类。汇聚子类会得到,中间子类从公共基类继承下来的多份成员。

问题:

汇聚子类会得到,中间子类从公共基类继承下来的多份成员,造成空间浪费,没有必要,还会对公共基类的成员多次初始化,或释放。

1.2 格式

                 A       --------公共基类/    \B      C    ------- 中间子类\    /D       --------汇聚子类

 解决:虚继承

#include <iostream>using namespace std;//封装公共基类 家具 类
class Jiaju
{
private:string color;
public://无参构造Jiaju() {cout << "家具的无参构造函数" << endl;}//有参构造Jiaju(string n):color(n){cout << "家具的有参构造函数" << endl;}
};//中间子类
//封装 沙发的类
class Sofa:public Jiaju
{
private:string sitting;
public://无参构造Sofa() {cout << "沙发的无参构造" << endl;}//有参构造函数Sofa(string s,string c):Jiaju(c),sitting(s){cout << "沙发的有参构造" << endl;}void display(){cout << sitting << endl;}
};//中间子类
//封装 床 类
class Bed:public Jiaju
{
private:string sleep;public://无参Bed() {cout << "床的无参构造" << endl;}//有参Bed(string s,string c):Jiaju(c),sleep(s){cout << "床的有参构造" << endl;}void display(){cout << sleep << endl;}
};//汇聚子类
//封装 沙发床类  继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:int w;
public://Sofa_Bed(){cout << "沙发床的无参构造" << endl;}//有参构造Sofa_Bed(string sit, string s, int w,string c):Bed(s,c),Sofa(sit,c),w(w){cout << "沙发床的有参构造" << endl;}
};int main()
{
//    Sofa_Bed s;Sofa_Bed s1("可坐","可躺",123,"pink");return 0;
}

二、虚继承

2.1 作用

可以让汇聚子类只保留一份 中间子类从公共基类继承下来的成员。

2.2 格式

在中间子类的继承方式前 加上 virtual

class 类名 : virtual 继承方式 类名   //中间子类
{中间子类的拓展;
};

2.3注意

1> 中间子类虚继承公共基类后,汇聚子类的初始化列表,先调用中间子类的有参构造函数,中间子类再调用公共基类的有参构造函数,但是呢,虚继承之后,只保留一份中间子类从公共基类继承下来的有参构造函数,意味着不知道调用哪一个中间子类继承下来的公共基类的构造函数,这样就会默认调用公共基类的无参构造函数。

2> 如果汇聚子类想要对公共基类的数据成员初始化,需要显性调用公共基类的构造函数。

#include <iostream>using namespace std;//封装公共基类 家具 类
class Jiaju
{
private:string color;
public://无参构造Jiaju() {cout << "家具的无参构造函数" << endl;}//有参构造Jiaju(string n):color(n){cout << "家具的有参构造函数" << endl;}
};//中间子类
//封装 沙发的类
class Sofa:virtual public Jiaju  //中间子类虚继承公共基类
{
private:string sitting;
public://无参构造Sofa() {cout << "沙发的无参构造" << endl;}//有参构造函数Sofa(string s,string c):Jiaju(c),sitting(s){cout << "沙发的有参构造" << endl;}void display(){cout << sitting << endl;}
};//中间子类
//封装 床 类
class Bed:virtual public Jiaju  //中间子类虚继承公共基类
{
private:string sleep;public://无参Bed() {cout << "床的无参构造" << endl;}//有参Bed(string s,string c):Jiaju(c),sleep(s){cout << "床的有参构造" << endl;}void display(){cout << sleep << endl;}
};//汇聚子类
//封装 沙发床类  继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:int w;
public://Sofa_Bed(){cout << "沙发床的无参构造" << endl;}//有参构造Sofa_Bed(string sit, string s, int w,string c):Jiaju(c),Bed(s,c),Sofa(sit,c),w(w) //需要在汇聚子类中显性调用公共基类的有参构造函数{cout << "沙发床的有参构造" << endl;}
};int main()
{
//    Sofa_Bed s;Sofa_Bed s1("可坐","可躺",123,"pink");return 0;
}

三、多态

类的三大属性:封装、继承、多态

静态多态(函数重载)、动态多态(运行时)

一种形式多种状态

多态就像一个人,可以有很多角色或者行为,取决于不同情境

父类的指针或者引用,指向或初始化子类的对象,调用子类对父类重写的函数,进而展开子类的功能。

3.1函数重写

1> 必须有继承关系

2> 子类和父类有同名同类型的函数

3> 父类中的该函数必须是虚函数

3.2 虚函数

1> 在函数前加上 virtual ---->该函数是虚函数

2> 虚函数满足继承,也就是说父类中该函数是虚函数,继承到子类中,该函数依旧是虚函数,如果子类再被继承,“孙类”中该函数还是虚函数....

#include <iostream>using namespace std;// 封装 周 这个类
class Zhou
{
private:string name;int age;
public://无参构造Zhou() {}//有参构造函数Zhou(string n, int a):name(n),age(a){}//virtual void speek()  //表示该函数是虚函数{cout << "阿巴阿巴。。" << endl;}
};//封装 周老师  类,继承于周类
class Teacher:public Zhou
{
private:int id;public://无参构造Teacher() {}//有参构造Teacher(string n, int a, int d):Zhou(n,a),id(d){}//void speek(){cout << "看我,上多态,认真听讲" << endl;}
};//封装 游戏玩家 类 继承于Zhou类
class Player:public Zhou
{
private:string game;
public://。。Player() {}//有参构造Player(string name, int age, string g):Zhou(name,age),game(g){}//void speek(){cout << "稳住,我们能赢" << endl;}
};int main()
{Teacher t("zhangsan",34,1001);Zhou *p; //父类的指针p = &t;  //父类的指针,指向子类对象  相当于承当老师这个角色p->speek();   // 上课Player g("lisi",45,"王者");p = &g; //此时是游戏玩家这个角色p->speek();return 0;
}

3.3 赋值兼容规则

父类的指针或者引用,指向或初始化子类的对象

3.4 多态中,函数重写的原理

  • 类中有虚函数时,类里就会有一个虚指针,虚指针也满足继承
  • 虚指针在类的最前面,虚指针指向了一个虚函数表,虚函数表里记录了虚函数,包括子类对父类重写的函数。
  • 虚指针和虚函数表是实现多态的重要机制。

3.5 虚析构函数

虚析构函数用来解决 父类指针指向子类时,父类指针释放,导致子类自拓展的空间没有得到释放

3.5.1 格式

virtual 析构函数
{}
#include <iostream>using namespace std;//封装 人 类
class Person
{
private:string name;
public://Person() {}//有参构造函数Person(string n):name(n){}virtual ~Person()  //虚析构函数  满足继承{cout << "Person::析构函数"  << endl;}
};//封装 学生  继承于人
class Stu:public Person
{
private:int id;
public://Stu(){}//有参构造Stu(string n , int i):Person(n),id(i){}~Stu(){cout << "Stu::析构函数" << endl;}
};int main()
{Person *p = new Stu("张三",1001);delete p;   //如果没有虚析构函数,进行释放p是,子类自己拓展的空间就没有释放--内存泄漏return 0;
}

3.6 纯虚函数

当父类中虚函数被子类用来重写,且没有定义的意义,这个时候,一般把父类中的虚函数设置成纯虚函数。

3.6.1格式

virtual 函数返回值类型 函数名(形参列表) = 0; //纯虚函数

四、抽象类

抽象类一般是用来被继承的,它不能实例化出具体的一个对象,抽象类中至少有一个纯虚函数。

如果子类没有对父类的纯虚函数重写,那么子类也是抽象类,不能实例化一个对象

#include <iostream>using namespace std;//..
class A  //抽象类
{
private:int a;
public:A() {}virtual void show() = 0;  //纯虚函数    
};class B:public A
{
public:B() {}    void show()  //如果子类没有对父类的纯虚函数重写,那么子类也是抽象类,不能实例化一个对象{}
};int main()
{B b;return 0;
}

五、模板

模板就是一个通用的模具。大大提高代码的复用性。

C++还有另一个编程思想 ,泛型编程,主要利用的技术 模板

C++中有两个重要的模板机制:函数模板和类模板

5.1模板的特点

1> 模板不能直接使用,它只是一个框架

2> 模板不是万能的

5.2 函数模板

5.2.1作用

建立一个通用的函数,其返回值类型或者形参类型 不具体制定,用一个虚拟的类型来代替。

5.2.2 格式

template <typename T>
函数的声明或定义

解释:

template ----->表示开始创建模板

typename -->表明后面的符号是数据类型,typename 也可以用class代替

T ----->表示数据类型,可以其他符号代替

#include <iostream>using namespace std;//创建函数模板
template <typename T>
void fun(T &a, T &b)
{T temp;temp = a;a = b;b = temp;
}//void fun(int &a, int &b)
//{
//    int temp;
//    temp = a;
//    a = b;
//    b = temp;//}
//void fun(double &a, double &b)
//{
//    double temp;
//    temp = a;
//    a = b;
//    b = temp;
//}//void fun(char &a, char &b)
//{
//    char temp;
//    temp = a;
//    a = b;
//    b = temp;
//}int main()
{int a = 10, b = 20;fun(a,b);cout << a << "  " << b << endl;double c = 1.3, d = 1.4;fun(c, d);cout << c <<  "  " <<  d << endl;return 0;
}

 六、练习

1.定义一个基类 Animal,其中有一个虚函数 perform(),用于在子类中实现不同的表演行为。

以下是一个简单的比喻,将多态概念与生活中的实际情况相联系:

比喻:动物园的讲解员和动物表演

想象一下你去了一家动物园,看到了许多不同种类的动物,如狮子、、猴子等。现在,动物园里有一位讲解员,他会为每种动物表演做简单的介绍。

在这个场景中,我们可以将动物比作是不同的类,而每种动物表演则是类中的函数。而讲解员则是一个基类,他可以根据每种动物的特点和表演,进行相应的介绍。

#include <iostream>using namespace std;class Animal{
protected:string species;
public:Animal(){}Animal(string sp): species(sp){}virtual void perform(){}
};class lion:public Animal{
public:lion(){}lion(string species):Animal(species){}void perform(){cout << Animal::species << "跳火圈" << endl;}
};class elephant:public Animal{
public:elephant(){}elephant(string sp):Animal(sp){}void perform(){cout << Animal::species << "踩背" << endl;}
};class monkey:public Animal{
public:monkey(){}monkey(string sp):Animal(sp){}void perform(){cout << Animal::species << "偷桃" << endl;}
};int main()
{lion it1("辛巴");Animal *p;p = &it1;p->perform();elephant it2("非洲象");p = &it2;p->perform();monkey it3("峨眉山猴子");p = &it3;p->perform();return 0;
}

 结果为:

2.用函数模板实现不同数据类型的交换功能。

#include <iostream>using namespace std;
template <typename T>void fun(T *a, T *b)
{T temp;temp = *a;*a = *b;*b = temp;
}int main()
{int a = 10;int b = 50;char c = 'C';char d = 'D';fun(&a,&b);fun(&c,&d);cout << "a = " << a << " b = " << b << endl;cout << "c = " << c << " d = " << d << endl;return 0;
}

结果为:

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

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

相关文章

Java 语言实现插入排序算法

【引言】 插入排序算法是一种简单且常用的排序算法。它通过依次将未排序的元素插入已排序序列中的正确位置来达到排序的目的。本文将使用Java高级语言实现插入排序算法&#xff0c;并讲解其核心思想和代码实现。 【算法思想】 插入排序的核心思想是通过构建有序序列&#xff0…

C#_GDI+ 绘图编程入门

官网提供相关API GDI 基本图形功能_drawing 高级二维和矢量图形功能_drawing2D GDI 图像处理功能_Imaging GDI 排版功能_text Windows 窗体应用程序提供打印功能_Printing 像素 构成图像的最小单位就是像素&#xff1b;屏幕上显示不管是位图或者矢量图&#xff0c;当描述…

计算机竞赛 基于GRU的 电影评论情感分析 - python 深度学习 情感分类

文章目录 1 前言1.1 项目介绍 2 情感分类介绍3 数据集4 实现4.1 数据预处理4.2 构建网络4.3 训练模型4.4 模型评估4.5 模型预测 5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于GRU的 电影评论情感分析 该项目较为新颖&#xff0c;适合作为竞…

IP协议分片重组问题

分片是什么&&为什么会有分片 IP数据报分片的主要目的是为了防止IP数据报文长度超过下一跳链路MTU(最大传输单元)。 数据链路层之MTU 数据链路层中有一个东西叫做MTU&#xff08;最大传输单元&#xff09;&#xff0c;它的作用主要是控制上层给的数据报不要太大&#…

LabVIEW | 串口基础【自学】

转载 B站   up&#xff1a;不烧板子 地址&#xff1a;https://www.bilibili.com/read/cv9435378 原博图片不清楚&#xff0c;自己重新跟学截图自留&#xff0c;侵删 文章目录 一、串口基础1.串口发送&#xff08;1&#xff09;简单发送&#xff08;2&#xff09;循环发送&…

〔019〕Stable Diffusion 之 单图中绘制多人分区域写提示词 篇

✨ 目录 &#x1f388; 下载区域绘制插件&#x1f388; 区域绘制使用&#x1f388; 参数讲解和基础使用&#x1f388; Lora 自组&#x1f388; Lora 自组的使用&#x1f388; 分区扩散&#x1f388; 分区域提示 &#x1f388; 下载区域绘制插件 在绘制图片时&#xff0c;经常绘…

解决博客不能解析PHP直接下载源码问题

背景&#xff1a; 在网站设置反向代理后&#xff0c;网站突然不能正常访问&#xff0c;而是会直接下载访问文件的PHP源码 解决办法&#xff1a; 由于在搞完反向代理之后&#xff0c;PHP版本变成了纯静态&#xff0c;所以网站不能正常解析&#xff1b;只需要把PHP版本恢复正常…

【ARMv8 SIMD和浮点指令编程】NEON 乘法指令——乘法知多少?

NEON 乘法指令包括向量乘法、向量乘加和向量乘减,还有和饱和相关的指令。总之,乘法指令是必修课,在我们的实际开发中会经常遇到。 1 MUL (by element) 乘(向量,按元素)。该指令将第一个源 SIMD&FP 寄存器中的向量元素乘以第二个源 SIMD&FP 寄存器中的指定值,将…

IDEA软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 IntelliJ IDEA是一款流行的Java集成开发环境&#xff08;IDE&#xff09;&#xff0c;由捷克软件开发公司JetBrains开发。它专为Java开发人员设计&#xff0c;提供了许多高级功能和工具&#xff0c;使得开发人员能够更高效地编写…

stm32----SPI协议

一、概述 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;&#xff0c;是Motorola公司提出的一种同步串行接口技术&#xff0c;是一种高速、全双工、同步通信总线&#xff0c;在芯片中只占用四根管脚用来控制及数据传输&#xff0c;节约…

mysql 导入数据速度提升

1.修改配置 #增加MySQL占用的内存和存储空间 innodb_buffer_pool_size = 8G #增加key buffer size key_buffer_size = 8589934592; #增加最大连接数 max_connections=1000; 2.使用LOAD DATA INFILE命令

C语言 - 结构体、结构体数组、结构体指针和结构体嵌套

结构体的意义 问题&#xff1a;学籍管理需要每个学生的下列数据&#xff1a;学号、姓名、性别、年龄、分数&#xff0c;请用 C 语言程序存储并处理一组学生的学籍。 单个学生学籍的数据结构&#xff1a; 学号&#xff08;num&#xff09;&#xff1a; int 型姓名&#xff08;…

2.Redis 通用命令

Redis 中最核心的两个命令&#xff1a; set 作用&#xff1a;设置 key 对应的 value 值并存储进去。若key已包含一个值&#xff0c;则无论其类型如何&#xff0c;都会覆盖该值。在SET操作成功时&#xff0c;将丢弃与密钥相关联的任何先前生存时间。 对于上述这里的 key和val…

五、Kafka消费者

目录 5.1 Kafka的消费方式5.2 Kafka 消费者工作流程1、总体流程2、消费者组原理3、消费者组初始化流程4、消费者组详细消费流程 5.3 消费者API1 独立消费者案例&#xff08;订阅主题&#xff09;2 独立消费者案例&#xff08;订阅分区&#xff09;3 消费者组案例 5.4 生产经验—…

leetcode做题笔记116. 填充每个节点的下一个右侧节点指针

给定一个 完美二叉树 &#xff0c;其所有叶子节点都在同一层&#xff0c;每个父节点都有两个子节点。二叉树定义如下&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到…

实训笔记8.22

8.22笔记 8.22笔记一、Hive的HQL语法重点问题1.1 DDL1.1.1 Hive中数据表的分类问题1.1.2 特殊的数据类型 1.2 DML1.3 DQL1.3.1 查询语法和MySQL大部分都是一致的 1.4 讲了三个数据库的可视化工具1.4.1 navicat1.4.2 dbeaver1.4.3 chat2db 二、Hive中重点问题&#xff1a;Hive函…

Linux内核学习(十二)—— 页高速缓存和页回写(基于Linux 2.6内核)

目录 一、缓存手段 二、Linux 页高速缓存 三、flusher 线程 Linux 内核实现了一个被叫做页高速缓存&#xff08;page cache&#xff09;的磁盘缓存&#xff0c;它主要用来减少对磁盘的 I/O 操作。它是通过把磁盘中的数据缓存到内存中&#xff0c;把对磁盘的访问变为对物理内…

pytest fixture夹具,@pytest.fixture

fixture 是pytest 用于测试前后进行预备&#xff0c;清理工作的代码处理机制 fixture相对于setup 和teardown&#xff1a; fixure &#xff0c;命名更加灵活&#xff0c;局限性比较小 conftest.py 配置里面可以实现数据共享&#xff0c;不需要import 就能自动找到一些配置 setu…

聚类分析 | MATLAB实现基于AHC聚类算法可视化

聚类分析 | MATLAB实现基于AHC聚类算法可视化 目录 聚类分析 | MATLAB实现基于AHC聚类算法可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 AHC聚类算法&#xff0c;聚类结果可视化&#xff0c;MATLAB程序。 Agglomerative Hierarchical Clustering&#xff08;自底…

JVM ZGC垃圾收集器

ZGC垃圾收集器 ZGC&#xff08;“Z”并非什么专业名词的缩写&#xff0c;这款收集器的名字就叫作Z Garbage Collector&#xff09;是一款在JDK 11中新加入的具有实验性质[1]的低延迟垃圾收集器&#xff0c;是由Oracle公司研发的。 ZGC收集器是一款基于Region内存布局的&#…