C++ DAY6

一、菱形继承

又叫钻石继承,由公共子类派生出多个中间子类,又由多个中间子类派生出汇聚子类,汇聚子类

中间子类得到从公共基类继承下来的多个成员。

                  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;
}

由于汇聚子类会得到中间子类从公共基类继承下来的多份基类成员,故引出了虚继承的概念

二、虚继承

为了使汇聚子类只保存一份中间子类从公共基类继承的成员,使用了在中间子类继承方式前virtual

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

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;
}

 三、多态

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

 函数重载是静态多态(编译时多态),函数重写是动态多态(运行时多态)

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

 函数重写

1> 必须有继承关系

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

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

————虚函数指在函数前加上virtual,虚函数满足继承(父类中该函数是虚函数),继承到子类中,该函数依旧是虚函数,如果之后继续继承,继承出的函数仍是虚函数

#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;
}

赋值兼容规则

只适用于公有继承。对于保护或私有继承,这些规则不适用。

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

虚析构函数

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

#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;
}

四、抽象类

纯虚函数是在 C++ 中用于实现接口和抽象类的一种机制。纯虚函数在基类中声明但不定义,它没有函数体,只有一个函数原型,并且必须在派生类中被重写(覆盖)。

在基类中声明纯虚函数会自动生成一个虚函数表(vtable),该表包含指向类中所有虚函数(包括纯虚函数)的指针。每个具有虚函数的对象都有一个隐藏的成员,即虚指针(vptr),它在对象构造时自动设置,用于指向与该对象类型关联的虚函数表。

派生类必须重写所有基类中的纯虚函数,否则该派生类也会成为一个抽象类,不能被实例化。这种多态行为不仅适用于使用 new 动态创建的对象,也适用于自动(栈)或静态存储期的对象,只要你通过基类指针或引用来访问它们。

如果一个类没有任何数据成员并且只有纯虚函数,通常将其称为接口。虽然构造函数不能是虚函数或纯虚函数,但析构函数可以(并且通常应该)是虚函数,以确保正确的析构行为。

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

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

#include <iostream>
#include <string>// 基类(抽象类)
class Hero {
public:virtual void attack() = 0;  // 纯虚函数virtual void defend() = 0;  // 纯虚函数
};// 派生类1
class Warrior : public Hero {
public:void attack() override {std::cout << "Wqm attacks!" << std::endl;}
//  void defend() override {
//    std::cout << "Wqm defends!" << std::endl;
//  }
};
class Warrior2 : public Warrior {
public:
//  void attack() override {
//    std::cout << "Wqm attacks!" << std::endl;
//  }void defend() override {std::cout << "Wqm defends!" << std::endl;}
};// 派生类2
class Mage : public Hero {
public:void attack() override {std::cout << "Mage casts a spell!" << std::endl;}void defend() override {std::cout << "Mage uses a shield!" << std::endl;}
};int main() {Hero* hero1 = new Warrior2();Hero* hero2 = new Mage();hero1->attack();hero1->defend();hero2->attack();hero2->defend();delete hero1;delete hero2;hero1=nullptr;hero2=nullptr;return 0;
}

五、模板

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

两个重要的模板机制:函数模板和类模板

                                                ​​​​​​​        ​​​​​​​只是一个框架并不是万能的

5.1函数模板

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

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;
}

作业

#include <iostream>
#include <string>// 基类(抽象类)
class Animal {
public:virtual void perform() = 0;  // 纯虚函数virtual void size()=0;virtual ~Animal(){}
};class Lion : public Animal {
public:void perform() override{std::cout << "Jump" << std::endl;}void size() override{std::cout << "big" << std::endl;}
};class Tiger : public Animal {
public:void perform() override{std::cout << "Sit Down" << std::endl;}void size() override{std::cout << "big" << std::endl;}
};int main() {Animal* hero1 = new Lion();Animal* hero2 = new Tiger();hero1->perform();hero1->size();hero2->perform();hero2->size();delete hero1;delete hero2;hero1=nullptr;hero2=nullptr;return 0;
}

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

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

相关文章

高忆管理:科创板代码多少开头?

科创板在上海证券买卖所正式开市&#xff0c;这是我国股票商场上的一次重磅改革。科创板旨在推进我国科技立异式企业的发展&#xff0c;招引更多高科技企业到A股上市。那么&#xff0c;科创板的代码多少最初呢&#xff1f;这个问题也让许多投资者和重视者非常重视。接下来&…

Java简便集成工作流(activiti),通用审批系统

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端分离部署开发模式&#xff0c;快速开发平…

用NeRFMeshing精确提取NeRF网络中的3D网格

准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功&#xff0c;但在准确表示底层几何方面存在不足。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展&#xff0c;例如 NVIDIA 的…

Ansible学习笔记(二)

3.ansible的使用示例&#xff08;playbook&#xff09; 1.创建mysql 账户和mysql 组的 playbook ---#create mysql user and group - hosts: allremote_user: roottasks:- name: create groupgroup: namemysql systemyes gid306- name: create useruser: namemysql systemyes…

【FreeRTOS】【STM32】中断详细介绍

文章目录 一、三种优先级的概念辨析1. 先理清楚两个概念&#xff1a;CPU 和 MPU2. Cortex-M3 内核与 STM32F1XX 控制器有什么关系3. 优先级的概念辨析① Cortex-M3 内核和 STM32F1XX 的中断优先级② FreeRTOS 的任务的优先级 二、 Cortex-M3 内核的中断优先级1. 中断编号2. 优先…

Prometheus关于微服务的监控

在微服务架构下随着服务越来越多,定位问题也变得越来越复杂,因此监控服务的运行状态以及针对异常状态及时的发出告警也成为微服务治理不可或缺的一环。服务的监控主要有日志监控、调用链路监控、指标监控等几种类型方式,其中指标监控在整个微服务监控中比重最高,也是实际生…

kafka学习笔记

1、kafka是什么&#xff1f; kafka是一个高吞吐&#xff0c;分布式&#xff0c;基于发布/订阅的消息系统&#xff0c;最大的特性就是可以实时的处理大量的数据以满足各种需求场景&#xff1a;日志收集&#xff0c;离线和在线的消息消费&#xff0c;等等 2、kakfa的基础架构&am…

SMC_TRAFO_GantryCutter2 (FB) 带刀片旋向龙门

裁布机&#xff1a;刀片按XY走向&#xff0c;偏转刀片角度。 pi&#xff1a;目标位置矢量&#xff08;x&#xff0c;y&#xff09;&#xff0c;插值器的输出 v&#xff1a;当前路径切线的矢量&#xff0c;插值器的输出 dOffsetX&#xff1a; x轴的附加偏移 dOffsetY&#xf…

NeRFMeshing - 精确提取NeRF中的3D网格

准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功&#xff0c;但在准确表示底层几何方面存在不足。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展&#xff0c;例如 NVIDIA 的 …

基于 xhr 实现 axios

基于 xhr 实现 axios 上面我们讲到二次封装 axios &#xff0c;但是现在我们尝试完全脱离 axios&#xff0c;自己实现一个 axios&#xff0c;由于 axios 底层是基于 xhr 做了二次封装&#xff0c;所以我们也可以尝试一下。 xhr 二次封装 src/plugins/xhr.js /*** 请求拦截器…

新能源电驱动总成相关标准简介

新能源电驱动总成相关标准简介 电驱动系统标准体系是电动汽车标准体系中重要的组成部分&#xff0c;其制定和更新对于保障电动汽车的使用性能和安全性能具有非常重要的作用。 随着电动汽车行业的快速发展和普及&#xff0c;电驱动系统的重要性也越来越凸显。为了确保电动汽车的…

循环神经网络(RNN) | 项目还不成熟 |还在初级阶段

一&#xff0c;定义 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习神经网络架构&#xff0c;专门设计用于处理序列数据&#xff0c;如时间序列数据、自然语言文本等&#xff08;一般用来解决序列问题&#xff09;。 因为它们具…

ResNet详解:网络结构解读与PyTorch实现教程

目录 一、深度残差网络&#xff08;Deep Residual Networks&#xff09;简介深度学习与网络深度的挑战残差学习的提出为什么ResNet有效&#xff1f; 二、深度学习与梯度消失问题梯度消失问题定义为什么会出现梯度消失&#xff1f;激活函数初始化方法网络深度 如何解决梯度消失问…

线性代数的学习和整理12: 矩阵与行列式,计算上的差别对比

目录 1 行列式和矩阵的比较 2 简单总结矩阵与行列式的不同 3 加减乘除的不同 3.1 加法不同 3.2 减法不同 3.3 标量乘法/数乘 3.3.1 标准的数乘对比 3.3.2 数乘的扩展 3.4 乘法 4 初等线性变换的不同 4.1 对矩阵进行线性变换 4.2 对行列式进行线性变换 1 行列式和…

算法通关村第5关【白银】| 哈希和栈经典算法题

1.两个栈实现队列 思路&#xff1a;两个栈&#xff0c;一个输入栈&#xff0c;一个输出栈。 当需要输入的时候就往inStack中插入&#xff0c;需要输出就往outStack中输出&#xff0c;当输出栈是空就倒出输入栈的数据到输出栈中&#xff0c;这样就保证了后插入的数据从栈顶倒入…

Docker修改容器ulimit的全部方案及各方案的详细步骤

要修改Docker容器的ulimit&#xff08;用户资源限制&#xff09;&#xff0c;有以下三种方案&#xff0c;每个方案的详细步骤如下&#xff1a; 方案一&#xff1a;在Dockerfile中设置ulimit 打开您的Dockerfile。在文件中添加以下命令来修改ulimit&#xff1a;RUN ulimit -n …

他们朝我扔泥巴(scratch)

前言 纯~~~属~~~虚~~~构~~~&#xff08;同学看完短视频要我做&#xff0c;蟹蟹你&#xff09; 用scratch做的&#xff0c;幼稚得嘞(&#xffe3;_&#xffe3;|||)呵呵&#xff08;强颜欢笑&#xff09; 完成视频 视频试了好久&#xff0c;就是传不上来&#xff0c;私信我加我…

LabVIEW开发灭火器机器人

LabVIEW开发灭火器机器人 如今&#xff0c;自主机器人在行业中有着巨大的需求。这是因为它们根据不同情况的适应性。由于消防员很难进入高风险区域&#xff0c;自主机器人出现了。该机器人具有自行检测火灾的能力&#xff0c;并通过自己的决定穿越路径。 由于消防安全是主要问…

开源项目-数据可视化分析平台

哈喽,大家好,今天给大家带来一个开源项目-数据可视化分析平台。项目通过SpringBoot实现 数据可视化分析平台主要有数据源管理,项目管理,数据集管理,图表管理,看板管理等功能 登录 数据源管理 数据源管理功能可以添加MySQL,Oracle,PostgreSQL等类型的数据源信息 项目…

24 WEB漏洞-文件上传之WAF绕过及安全修复

目录 WAF绕过上传参数名解析:明确哪些东西能修改?常见绕过方法&#xff1a;符号变异-防匹配( " ;)数据截断-防匹配(%00 ; 换行)重复数据-防匹配(参数多次)搜索引擎搜索fuzz web字典文件上传安全修复方案 WAF绕过 safedog BT(宝塔) XXX云盾 宝塔过滤的比安全狗厉害一些&a…