C++_20_多态

多继承会造成 菱形继承** 使用虚继承来解决

不是给爷爷类加 也不是给子类加 是给父类加 虚基指针和虚基表

多态

概念:

概念: 一个事物的多种形态,简称多态

如:

  • 对象的多态

    ​ 张三

    ​ 在对象面前 怂

    ​ 在朋友面前 谄媚

    ​ 在父母面前 孝顺

  • 事的多态

    ​ 吃饭

    ​ 中国人用筷子

    ​ 美国人用刀叉

    ​ 印度人用手抓

  • 事务的多态

    • 上行: 子类对象换为父类对象
    • 下行 : 父类对象换为子类对象
  • 事的多态

    • 重载:
    • 重写:
    • 重定义:

物的多态:

上行:

特点: 自动转换 无风险

概念:子类对象转换为父类对象

语法:

子类对象 转换为 父类对象

  • 父类名 &父类对象名 = 子类对象;

子类对象指针 转换为 父类对象指针

  • 父类名 *父类对象指针 = 子类对象指针;

示例:

在这里插入图片描述

注意:

子类对象转换为父类对象或父类对象指针后,使用转换后父类对象或父类对象指针 无法使用子类特有的成员

包括 成员对象 和 成员函数

下行:

概念: 父类对象 转换 为 子类对象 父类对象指针 转换为 子类对象指针

特点: 有风险 需要强制转换 语法就带

语法:

子类名 &子类对象 = ( 子类名& )父类对象名;

  • Cat cat = (Cat &) anim; // Cat &强制转换

子类名 子类对象指针 = ( 子类名 * ) 父类对象指针名;

事的多态

重载

  • 同一个类中函数名相同,形参列表不同,称为重载

重写

  • 继承关系中,子类成员函数与父类成员函数函数名相同,形参列表相同,返回值类型相同

重定义

  • 函数名相同,即为重定义 c不允许重定义 C++允许

虚函数:

概念: 使用 virtual 修饰的函数

语法:

 virtual 返回值类型 函数名(){函数体;}

原理: 使用 虚基指针和虚基表

特定:

  • 当子类重写 父类 提供的 虚 函数

  • 当子类对象转换为父类对象 ,使用转换的父类对象调用 重写的虚函数,此时执行的子类重写后的

未使用 虚函数 重写父类的函数后 造成想要的效果出现不了

在这里插入图片描述

  • 发现打印的是A 不是想要的B

  • 解决方式
    

    虚函数: virtual 父类函数 加 virtual

#include <iostream>
using namespace std;
// 虚函数 解决 继承重写的问题
class A
{
public:virtual void method(){cout << " 父类 A" << endl;}
};class B : public A
{
public:void method(){cout << " 子类 B" << endl;}
};
int main(int argc, char const *argv[])
{B b;A &a = b;   // 上行  将 b对象 转为 A 类对象a.method();return 0;
}//  有问题 没出预期效果 没出 B   应该出 B

在这里插入图片描述

  • 虚函数 是有函数体的 不知道才写纯虚 函数 知道就写虚函数 要是不知道函数体就写
    纯 虚函数 并子类重写 父类的所有纯虚函数 不然创建不了对象

纯虚函数:

  • 没有函数体
  • 如果一个类中有虚函数,该类无法直接创建对象,这种类称为抽象类
  • 子类继承于抽象类,要么重写所有纯虚函数,要么

概念:

  • 没有函数体的虚函数
  • 如果一个类中有纯虚函数,该类无法直接创建对象,这种类称为抽象类子类继承与抽象类,要么重写抽象类中所有的纯虚函数要么自己也是抽象类

语法:

virtua]返回值类型函数名(形参列表)= 0;

使用完 释放内存的时候 担心 内存释放的不干净

父类 anim 子类dog 释放dog 出现问题 出现 只释放了 anim 内存 而没释放 dog

释放 anim 就两者都释放掉了 但就是担心你释放的时候写错 忘记释放内存 使用虚析构造解决

在这里插入图片描述

在这里插入图片描述

#include <iostream>
using namespace std;// 纯虚函数class A{
public:
virtual void me01() = 0 ; // 纯虚函数 1virtual void me02() = 0 ; // 纯虚函数 2 只有重写父类的纯虚函数之后才能创建对象};class B :public A{public://重写父类所有纯虚函数  重写的不是全部的时候 就创建不了对象void me01(){cout<<"B 01"<<endl;}void me02(){cout<<"B 02"<<endl;}};int main(int argc, char const *argv[])
{B b;  //创建对象才正常   return 0;}

虚析构造:【*】

概念:

  • 使用 virtual 修饰的析构函数

特点:

  • 子类对象指针转换为父类对象指针,此时delete父类对象指针,只会调用父类析构函数
  • 如果父类析构函数为虚析构造,那么也将调用子类析构函数

语法: 【注意 是给父类中写 】

virtual ~父类名()
{}

示例:

在这里插入图片描述

在这里插入图片描述

纯虚析构:【**】

优化虚析函数版的

因为要分文件 所以优化用这个

概念 : 没有函数体的虚析构造

语法 :

virtual ~父类名()= 0;

注意 :

  • 类外实现
  • 纯虚析构也是纯虚函数
  • 顾纯虚析构的类也是抽象类,此时无法创建对象

案例:

小张是个宠物医生

张女士 养了一只狗叫旺财

李女士 养了一只猫叫布丁

分析:

存在的对象

​ 小张 张女士 李女士 旺财 布丁

类:

​ 动物:人类 医生类 ​ 狗类 猫类

​ A 动物类:

​ 成员变量: name

​ 成员函数: 1 speak 2 无参构造 3 有参构造 4 拷贝构造 5 纯虚析构

​ B 人类:

​ 特有成员: 宠物 [anim]

​ 重写父类speak函数

​ 无参构造 有参构造 拷贝构造 纯虚析构

​ C 医生类:

​ 特有函数: work:治病

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​ D 狗类

​ 重写父类speak函数

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​E 猫类

​ 重写父类speak函数

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​==============
创建对象

​ 建立关系

分文件编写:

头文件:

anim.h
#ifndef xx
#define xx
#include <iostream>
#include <stdlib.h>
#include <string.h>
class Anim
{
private:char *name;public:Anim();Anim(char *name);Anim(const Anim &anim);virtual ~Anim();                    // 纯虚析构  virtual ~父类名()= 0;virtual void speak(char *info) = 0; // 纯虚函数 virtua]返回值类型函数名(形参列表)= 0;char *getName() const;void setName(char *name);
};
#endif
person.h
#ifndef tt
#define tt
#include <iostream>
#include "anim.h"
using namespace std;
class Person : public Anim
{private:Anim* anim;public:Person();Person(char *name);Person(char *name,Anim* anim);Person(const Person &p);~Person() ; // 纯虚函数 virtua]返回值类型函数名(形参列表)= 0;Anim* getAnim() const;void setAnim(Anim*  anim);void speak(char *info);
};
#endif
doctor.h
#ifndef do
#define do
#include <iostream>
#include "person.h"
class Doctor : public Person
{
public:Doctor();Doctor(char *name);// virtual ~Doctor() = 0;~Doctor();void work(Anim *anim);
};
#endif
dog.cpp
#ifndef dogg
#define dogg
#include <iostream>
#include "anim.h"
class Dog : public Anim
{
public:Dog();Dog(char *name);// virtual ~Dog() = 0;  使用这个有问题~Dog();void speak(char *info);
};
#endif
cat.h
#ifndef catt
#define catt
#include <iostream>
#include "anim.h"
class Cat : public Anim
{
public:Cat();Cat(char *name);~Cat();void speak(char *info);
};
#endif

源文件

anim.cpp
#include "anim.h"
Anim::Anim() : name(NULL) {};
Anim::Anim(char *name)
{int len = strlen(name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,name);
}
Anim::Anim(const Anim &anim)
{int len = strlen(anim.name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,anim.name);
}
Anim::~Anim()
{if (name != NULL){free(name);name = NULL;}
}
char * Anim::getName() const
{return name;
}void Anim::setName(char *name)
{if (this->name != NULL){free (this->name);}int len = strlen(name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,name);
}
person.cpp
#include "person.h"
Person::Person() : anim(NULL) {}
Person::Person(char *name) : Anim(name), anim(NULL) {}
Person::Person(char *name, Anim *anim) : Anim(name), anim(anim) {}
Person::Person(const Person &person)
{// 因为形参 person 使用了const 修饰 意味着不能修改其成员// 此时使用person调用 其函数 系统担心 函数内部对其成员进行修改,// 顾调用 的函数必须是使用const 修饰的成员函数this->anim = person.getAnim(); char *name = person.getName();  //加const
}
Person::~Person() {} // 纯虚析构
Anim *Person::getAnim() const
{return anim;
}
void Person::setAnim(Anim *anim)
{this->anim = anim;
}
void Person::speak(char *info)
{cout << this->getName() << " "<<endl;
}
doctor.cpp
#include "doctor.h"
Doctor::Doctor() {}
Doctor::Doctor(char *name) : Person(name) {}
Doctor::~Doctor() {}
// 给宠物看病  将宠物传进来
void Doctor::work(Anim *anim)
{cout << this->getName() << "给" << anim->getName() << "看看病!" << endl;anim->speak(NULL);
}
cat.cpp
#ifndef catt
#define catt
#include <iostream>
#include "anim.h"
class Cat : public Anim
{
public:Cat();Cat(char *name);~Cat();void speak(char *info);
};
#endif
dog.cpp
#include "dog.h"
using namespace std;
Dog::Dog() {};
Dog::Dog(char *name) : Anim(name) {}
Dog::~Dog() {}
void Dog::speak(char *info)
{cout << getName() << ":" << "汪汪汪" << endl;
}

执行文件:

main.cpp
#include <iostream>
#include "anim.h"
#include "doctor.h"
#include "cat.h"
#include "dog.h"
#include "person.h"
using namespace std;
int main(int argc, char const *argv[])
{Doctor *d = new Doctor("小张");Dog *dog  = new Dog("旺财");Cat *cat =new Cat("大橘");Person* p1 = new Person("张女士",dog);Person* p2 = new Person("李女士",cat);d->work(p1->getAnim());d->work(p2->getAnim());return 0;
}

在这里插入图片描述

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

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

相关文章

rabbitmq容器化部署

需求 容器化部署rabbitmq服务 部署服务 找到如下官网信息版本 官网版本发布信息 这里看到最新版本是3.13版本&#xff0c;这里在3.13中找一个版本下载容器镜像即可。 找到dockrhub.com中 找到3.13.2版本镜像。 容器服务安装此处省略 现在下载容器镜像需要配置容器代理 ~#…

免费像素画绘制软件 | Pixelorama v1.0.3

Pixelorama 是一款开源像素艺术多工具软件&#xff0c;旨在为用户提供一个强大且易于使用的平台来创作各种像素艺术作品&#xff0c;包括精灵、瓷砖和动画。这款软件以其丰富的工具箱、动画支持、像素完美模式、剪裁遮罩、预制及可导入的调色板等特色功能&#xff0c;满足了像素…

Win电脑使用Ollama与Open Web UI搭建本地大语言模型运行工具

文章目录 前言1. 运行Ollama2. 安装Open WebUI2.1 在Windows系统安装Docker2.2 使用Docker部署Open WebUI 3. 安装内网穿透工具4. 创建固定公网地址 前言 本文主要介绍如何在Windows系统快速部署Ollama开源大语言模型运行工具&#xff0c;并安装Open WebUI结合cpolar内网穿透软…

8. Transforms的使用(三)-- Resize

Transforms的使用(三) 1. 为什么要使用Resize 在模型的训练过程中往往需要图片数据的维度相同,才能适应深度学习模型中的相关神经网络结构,这时候就需要使用Resize保证所有的图片保持相同的尺寸2. 使用Resize调整图片的尺寸 在pytorch2.3的版本上,Resize()支持对Tensor类…

Vue2学习笔记(01计算属性和监视属性)

1、事件修饰符 2、计算属性-computed 要显示的数据不存在&#xff0c;要通过计算得来。在computed对象中定义计算属性。在页面中使用{{方法名}}来显示计算的结果。 3、监视属性-watch 通过vm对象的$watch()或watch配置来监视指定的属性当属性变化时,回调函数自动调用,在函数内…

2024.9.14 Python与图像处理新国大EE5731课程大作业,马尔可夫随机场和二值图割,校正立体图像的深度

1.马尔科夫随机场和二值图割 马尔可夫随机场&#xff08;MRF, Markov Random Field&#xff09;&#xff1a; MRF 是一种用来描述图像像素之间空间关系的概率模型。它假设图像中的像素不仅取决于自身的值&#xff0c;还与周围像素有关。这种模型经常用于图像分割、去噪等任务。…

【C++】关键字、命名空间、输入和输出、缺省参数的深入了解

目录 一、C关键字二、命名空间2.1 为什么存在命名空间&#xff1f;2.2 命名空间定义2.3 命名空间使用 三、C输入&输出四、缺省函数4.1 缺省函数分类 总结 一、C关键字 C一共有63个关键字 其中红色圈出来的32个关键字同时也是C语言的 二、命名空间 2.1 为什么存在命名空间…

MySQL 按照条件(分组)只取一个形成列表 group max

方法一、通过Max形成where条件 SELECTt1.* FROMbiz_customer_hold AS t1 WHEREt1.ch_create_time ( SELECT MAX( ch_create_time ) FROM biz_customer_hold AS t2 WHERE t2.ch_cust_no t1.ch_cust_no ) ORDER BYt1.ch_create_time DESC,t1.ch_hold_time DESC 方法二、通…

LabVIEW编程快速提升的技术

在LabVIEW程序员的成长过程中&#xff0c;很多技术和概念看似简单、常用&#xff0c;但真正掌握并能熟练运用&#xff0c;往往需要踏踏实实的实践与积累。没有什么是能够一蹴而就的&#xff0c;唯有通过不断的专注与深入&#xff0c;才能获得显著的提升。要想在LabVIEW开发上取…

ICPC网络赛 以及ACM训练总结

一、训练反思 关于我自己暑假期间训练的反思&#xff0c;我承认无论是因为什么原因&#xff0c;我自己浪费我整整一个暑假的时间&#xff0c;暑假期间正是我们集训的关键时期&#xff0c;这期间没有任何的事情来打扰我们学习&#xff0c;而我却熬夜&#xff0c;白天训练懈怠&a…

力扣题解2390

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述​&#xff08;中等&#xff09;&#xff1a; 从字符串中移除星号 给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。 移除星号…

GIS在线监测SF6密度微水传感器免焊接格兰头航插插头

概述 GIS&#xff08;气体绝缘金属封闭开关设备&#xff09;中的SF6&#xff08;六氟化硫&#xff09;气体密度微水传感器航插技术是指在GIS设备中安装SF6气体密度和微水传感器&#xff0c;以实现对SF6气体状态的在线监测。这些传感器能够实时监测SF6气体的密度、微水含量以及其…

Acrobat 9 安装教程

软件介绍 Adobe Acrobat 是由Adobe公司开发的一款PDF&#xff08;Portable Document Format&#xff0c;便携式文档格式&#xff09;编辑软件。借助它&#xff0c;可以以PDF格式制作和保存文档&#xff0c;以便于浏览和打印&#xff0c;同时还可以使用一些高级工具来创建、编辑…

CSS—4

1.定位 1.相对定位 2.绝对定位 3.固定定位 4.粘性定位 5.定位的特殊应用 2.布局-版心 3.布局-常用布局名词 4.布局-重置默认样式

PCIe进阶之TL:Memory, I/O, and Configuration Request Rules TPH Rules

1 Memory, I/O, and Configuration Request Rules 下述规则适用于 Memory 请求、IO 请求和配置请求。 除了公共的 header 字段外,所有 Memory 请求、IO 请求和配置请求还包括以下字段: (1)Requester ID[15:0] 和 Tag[9:0],组成了 Transaction ID 。 (2)Last DW BE[3:0]…

BERT 论文逐段精读【论文精读】

BERT: 近 3 年 NLP 最火 CV: 大数据集上的训练好的 NN 模型&#xff0c;提升 CV 任务的性能 —— ImageNet 的 CNN 模型 NLP: BERT 简化了 NLP 任务的训练&#xff0c;提升了 NLP 任务的性能 BERT 如何站在巨人的肩膀上的&#xff1f;使用了哪些 NLP 已有的技术和思想&#xff…

基于AutoDL部署langchain-chatchat-0.3.1实战

一、租用AutoDL云服务器&#xff0c;配置环境 1.1 配置AutoDL环境 注册好autodl账户之后&#xff0c;开始在上面租服务器&#xff0c;GPU我选择的是RTX4090*2&#xff0c;西北B区&#xff0c;基础镜像选择的是Pytorch-2.3.0-python-3.12&#xff08;ubuntu22.04&#xff09;-…

SAP Fiori UI5-环境搭建-2022-2024界面对比

文章目录 一、Fiori项目初始化实际操作第一步&#xff1a;新建文件夹&#xff08;项目文件&#xff09;第二步&#xff1a;打开我们项目第三步&#xff1a;打开终端 部署环境第四步: XML中新增文本 二、 2023年Vscode中Fiori界面三 、2024年Vscode中Fiori界面 一、Fiori项目初始…

PHP仓库物资出入库管理系统小程序源码

仓库物资出入库管理系统&#xff1a;让库存管理变得井井有条 **&#x1f4e6; 开篇&#xff1a;告别混乱&#xff0c;拥抱智能库存时代 还在为仓库里堆积如山的物资和繁琐的出入库记录而头疼吗&#xff1f;是时候告别那些混乱的日子了&#xff01;“仓库物资出入库管理系统”应…

Android平台RTMP|RTSP播放器如何回调YUV或RGB数据?

技术选型 我们知道&#xff0c;Android平台一般RTMP|RTSP播放器通常不直接提供回调YUV或RGB数据的功能。如果播放端有视觉分析或类似的需求&#xff0c;需要播放端&#xff0c;能支持YUV或ARG的数据回调&#xff0c;一般来说&#xff0c;可参考的方法如下&#xff1a; 1. 使用…