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.mzph.cn/diannao/54010.shtml

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

相关文章

python 读取excel数据存储到mysql

一、安装依赖 pip install mysql-connector-python 二、mysql添加表students CREATE TABLE students (ID int(11) NOT NULL AUTO_INCREMENT,Name varchar(50) DEFAULT NULL,Sex varchar(50) DEFAULT NULL,PRIMARY KEY (ID) ) ENGINEInnoDB AUTO_INCREMENT13 DEFAULT CHARSETu…

二十三种设计模式之原型模式

一.什么是原型模式 ‌‌原型模式是一种创建型对象设计模式&#xff0c;它通过复制一个已经创建的实例&#xff08;即原型对象&#xff09;来创建一个和原型对象相同的新对象。‌ 这种模式在面向对象软件设计中非常有用&#xff0c;因为它允许通过复制现有对象来快速生成多个相似…

springboot修改组件扫描包位置

步骤很详细&#xff0c;直接上教程 问题分析 默认情况下组件扫描包范围为启动类所在包及其子包 解决方法 我们只需要在启动类上面加个注解配置扫描范围 效果演示 温馨提示 非必要不建议修改&#xff0c;按规范创建项目结构一般不会出现这个问题

AI+代码审核平台CodeSec获CCIA中国网络安全创新创业大赛总决赛三等奖

近日&#xff0c;由中央网信办指导&#xff0c;中国网络安全产业联盟&#xff08;CCIA&#xff09;主办的2024年中国网络安全创新创业大赛总决赛及颁奖典礼在国家网络安全宣传周落下帷幕。开源网安“AI代码审核平台CodeSec V4.0” 凭借在AI方向的技术创新、技术突破及功能应用创…

热门远程控制工具大盘点,职场必备

如果你想要进行远程数据操作那向日葵远程控制软件你肯定听说过吧。如果你是想要远程运维&#xff0c;远程办公&#xff0c;数据传输&#xff0c;这些远程控制工具都可以实现。这次我将介绍几款我身边小伙伴都在使用的远程控制工具。 1.向日葵远程控制 链接直达&#xff1a;ht…

Python 数学建模——Prophet 时间序列预测

文章目录 前言原理使用方法&#xff08;初级&#xff09;代码实例Prophet 高级应用add_seasonality 添加自定义周期性add_regressor 添加外生变量交叉检验 前言 Prophet 是 Facebook 团队开发的一个时间序列分析工具&#xff0c;相比传统的 ARMA 时间序列分析&#xff0c;能够综…

常见 HTTP 状态码详解与Nginx 文件上传大小限制

在我们日常使用 Nginx 搭建网站或应用服务时&#xff0c;可能会遇到很多与文件上传和请求响应相关的问题。今天我们就来聊聊 如何限制文件上传的大小&#xff0c;并介绍一些常见的 HTTP 状态码 及其在 Nginx 中的处理方式。 一、文件上传大小限制 有时&#xff0c;我们需要限…

通过覆写 url_for 将 flask 应用部署到子目录下

0. 缘起 最近用 flask 写了一个 web 应用&#xff0c;需要部署到服务器上。而服务器主域名已经被使用了&#xff0c;只能给主域名加个子目录进行部署&#xff0c;比如主域名 example.org &#xff0c;我需要在 example.org/flask 下部署。这时 flask 应用里的内部连接们就出现…

github远程仓库环境搭建及使用

目录 1、创建一台虚拟机 centos 源的配置 备份源 修改源 重新加载缓存 安装软件 配置epel 2、关闭防火墙和selinux 关闭防火墙 临时关闭SELinux 永久关闭SELinux&#xff1a;编辑SELinux的配置文件 配置文件的修改内容 3、git是本地仓库&#xff0c;linux系统中一…

Qt常用控件——QDateTimeEdit

文章目录 QDateTimeEdit核心属性及信号时间计算器 QDateTimeEdit核心属性及信号 QDateEdit作为日期的微调框QTimeEdit作为时间的微调框QDateTimeEdit作为时间日期的微调框 它们的使用方式都是类似的&#xff0c;本篇以QDateTimeEdit作为示例 核心属性&#xff1a; 属性说明…

【秒达开源】多功能中文工具箱源码:自部署 全开源 轻量级跨平台 GPT级支持+高效UI+Docker

【秒达开源】多功能中文工具箱源码发布&#xff1a;自部署、全开源、轻量级跨平台&#xff0c;GPT级支持高效UI&#xff0c;Docker/便携版任选&#xff0c;桌面友好丰富插件生态 这是一款集大成之作&#xff0c;专为追求高效与便捷的用户量身打造。它不仅支持完全自部署&#…

远程访问电脑共享文件

远程访问电脑共享文件&#xff0c;可以通过多种方法实现&#xff0c;每种方法都有其特点和适用场景。以下是一些常见的方法及其步骤&#xff1a; 一、使用Microsoft远程桌面 启用远程桌面&#xff1a; 在目标电脑上&#xff0c;打开“开始”菜单&#xff0c;选择“设置”>“…

教育培训小程序开发,简单实用的入门指南

教育培训小程序可以帮助教育机构和个人老师提供更灵活的在线教学服务&#xff0c;满足学生的学习需求。对于初学者来说&#xff0c;开发一个功能齐全的教育培训小程序并不复杂&#xff0c;只需掌握一些基础的开发知识和工具即可。本文将带你了解如何使用微信小程序开发工具&…

SpringBoot开发——使用@Slf4j注解实现日志输出

文章目录 1、Lombok简介2、SLF4J简介3、实现步骤3.1 创建SpringBoot项目3.2 添加依赖3.3 使用 Slf4j 注解3.4 输出日志信息 4、结论 在现代Java开发中&#xff0c;日志记录是至关重要的。它不仅帮助开发者调试代码&#xff0c;还便于监控系统运行状态和性能。 Lombok 和 SLF4J …

【Android】Room—数据库的基本操作

引言 在Android开发中&#xff0c;数据持久化是一个不可或缺的部分。随着应用的复杂度增加&#xff0c;选择合适的数据存储方式变得尤为重要。Room数据库作为Android Jetpack架构组件之一&#xff0c;提供了一种抽象层&#xff0c;使得开发者能够以更简洁、更安全的方式操作SQ…

快速搭建最简单的前端项目vue+View UI Plus

1 引言 ‌‌Vue是一套用于构建Web前端界面的渐进式JavaScript框架。‌‌它以其易学易用、性能出色、灵活多变而深受开发者喜爱&#xff0c;并且与其他前端框架&#xff08;如‌React和‌Angular&#xff09;相比&#xff0c;在国内市场上受到了广泛的认可和使用。点击进入官方…

AI问答-HTTP:理解 Content-Disposition

一、简介 Content-Disposition是HTTP协议中的一个响应头字段&#xff0c;它主要用于指示如何处理响应的内容以及如何呈现给用户。这个字段是MIME协议类型的扩展&#xff0c;用于指导MIME用户代理&#xff08;如浏览器&#xff09;如何显示附加的文件。Content-Disposition的主…

yolo自动化项目实例解析(二)ui页面整理

我们在上一章整理main.py 的if __name__ __main__: 内容还留下面这一段&#xff0c; app QApplication(sys.argv) # 初始化Qt应用ratio screen_width / 2560 # 分辨率比例# 设置全局字体大小# 计算字体大小base_font_size 13# 基准字体大小&#xff0c;适合1920*1080分辨…

【数据结构与算法 | 灵神题单 | 合并链表篇】力扣2, 21, 445, 2816

1. 力扣2&#xff1a;两数相加 1.1 题目&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可…

vue3 +百度地图 实现 地点检索,输入联想,经纬度,逆地理编码,创建标记,label等

由于百度地图文档确实有点欠缺&#xff0c;在这里记录一下 vue3 百度地图&#xff08;js api 3.0&#xff09;实现效果如下实现方式注意事项 vue3 百度地图&#xff08;js api 3.0&#xff09; 需求&#xff1a; 地图弹框组件&#xff0c;可以搜索地图点&#xff0c;输入联想…