C++_20_多态

news2024/11/15 19:51:57

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

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

多态

概念:

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

如:

  • 对象的多态

    ​ 张三

    ​ 在对象面前 怂

    ​ 在朋友面前 谄媚

    ​ 在父母面前 孝顺

  • 事的多态

    ​ 吃饭

    ​ 中国人用筷子

    ​ 美国人用刀叉

    ​ 印度人用手抓

  • 事务的多态

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

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

物的多态:

上行:

特点: 自动转换 无风险

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

语法:

子类对象 转换为 父类对象

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

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

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

示例:

在这里插入图片描述

注意:

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

包括 成员对象 和 成员函数

下行:

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

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

语法:

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

  • 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 ; // 纯虚函数 1
   virtual 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.coloradmin.cn/o/2138638.html

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

相关文章

Axure科技感大屏系统设计:智慧农场管理平台

在数字化转型的浪潮中&#xff0c;数据可视化作为连接现实世界与数字世界的桥梁&#xff0c;正以前所未有的速度改变着各行各业的面貌。智慧农业作为现代农业的重要发展方向&#xff0c;其管理平台的数据大屏设计尤为重要&#xff0c;它不仅是农场运营状况的直接展示窗口&#…

3. Python计算水仙花数

Python计算水仙花数 一、什么是水仙花数&#xff1f; 百度答案 二、怎样使用Python计算水仙花数&#xff1f; 这里需要for循环&#xff0c;if判断&#xff0c;需要range()函数&#xff0c;需要知道怎么求个位数&#xff0c;十位数&#xff0c;百位数… 1. For循环 语句结…

【Android Studio】API 29(即Android 10)或更高版本,在程序启动时检查相机权限,并在未获取该权限时请求它

文章目录 1. 在AndroidManifest.xml文件中&#xff0c;声明相机权限&#xff1a;2. 在你的Activity中&#xff08;例如MainActivity&#xff09;测试 1. 在AndroidManifest.xml文件中&#xff0c;声明相机权限&#xff1a; <uses-feature android:name"android.hardwar…

OS:初识操作系统——邂逅与启航

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;实践是检验真理的唯一标准&#xff01;&#xff01;&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 前言 各位uu好&#xff0c;现在我们要开始一个新的篇章——操作…

信息安全:守护数字世界的坚固堡垒

信息安全&#xff1a;守护数字世界的坚固堡垒 一、信息安全的重要性与意义 信息安全在个人、企业和社会层面都具有至关重要的意义。 在个人层面&#xff0c;信息安全保护隐私至关重要。在数字化时代&#xff0c;我们的个人信息如银行账户、社交媒体账户等容易受到威胁。一旦…

【代码随想录训练营第42期 续Day58打卡 - 图论Part8 - Dijkstra算法

目录 一、Dijkstra算法 实现方式 1、使用优先队列&#xff08;最小堆&#xff09; 2、朴素法&#xff08;简单数组&#xff09; 二、经典例题 题目&#xff1a;卡码网 47. 参加科学大会 题目链接 题解&#xff1a;朴素Dijkstra 三、小结 一、Dijkstra算法 刚入门Dijks…

【Git】常见命令(仅笔记)

文章目录 创建/初始化本地仓库添加本地仓库配置项提交文件查看仓库状态回退仓库查看日志分支删除文件暂存工作区代码远程仓库使用 .gitigore 文件让 git 不追踪一些文件标签 创建/初始化本地仓库 git init添加本地仓库配置项 git config -l #以列表形式显示配置项git config …

【免费】CISSP官方习题集第4版

伴随2004年4月CISSP新大纲发布&#xff0c;CISSP官方习题集第4版(OPT v4)已于2024年5月出版&#xff1a; 本人维护的中英对照8个知识域分章节练习已同步更新完成&#xff0c;在保持v3版内容基础上&#xff0c;增补了所有v4新内容&#xff0c;免费供考友们使用&#xff0c;访问方…

Requests-HTML模块怎样安装和使用?

要安装和使用Requests-HTML模块&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开命令行界面&#xff08;如Windows的命令提示符或Mac的终端&#xff09;。 使用pip命令安装Requests-HTML模块。在命令行中输入以下命令并按回车键执行&#xff1a; pip install request…

mp4文件解析

mp4格式与Annexb格式不同 实际送到GPU中解码数据是 00 00 01 + 编码数据,三个字节标识加解码数据 解析开始: for (uint32_t sampleIndex = 0; sampleIndex < track.sample_count; ++sampleIndex) {//----------------------------------------------------------…

28 线性表 · 栈

目录 一、概念与结构 &#xff08;一&#xff09;概念 1、栈 2、压栈 3、出栈 4、底层实现 二、栈的实现 三、栈的算法题 一、概念与结构 &#xff08;一&#xff09;概念 1、栈 一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作。进行数据插…

idea连接数据库大避雷!!!

再跟着黑马学习的时候&#xff0c;用黑马的资料安装的数据库&#xff0c;命令行能正常启动&#xff0c;SQLyog也能正常连接&#xff0c;就是tmd idea连接不了。不论是原始的jdbc,还是其它方式都不行&#xff0c;一直报错&#xff1a; 然后就各种搜&#xff0c;有的说数据库驱动…

【JavaEE初阶】多线程(4)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程安全的 第四个原因 代码举例: 分析原因 解决方法 方法1 方法2 wait(等待)和notify(通知) wait和sleep区别 线程安全的 第四个原因 内存可见性,引起的线程安全问…

AI辅助癌症诊断取得了进展

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

服务发现和代理实例的自动更新

1.服务发现的两种方式 StartFindService 方法 这是一个在后台启动的连续 “FindService” 活动&#xff0c;当服务实例的可用性发生变化时&#xff0c;会通过回调通知调用者。 它返回一个FindServiceHandle&#xff0c;可通过调用StopFindService来停止正在进行的监视服务实例…

pwn题目搭建过程中glibc出现问题的解决方案

前言&#xff1a; 在做pwn的堆题时&#xff0c;会遇到不同版本的glibc。为了更好地与远程环境对应&#xff0c;我们可以通过patchelf和glibc-all-in-one来更换程序动态加载时的glibc。简单介绍一下&#xff0c;glibc-all-in-one用来下载需要的glibc包&#xff0c;然后用petche…

【Git】初识Git

本篇文章的环境是在 Ubuntu/Linux 环境下编写的 文章目录 版本控制器Git 基本操作安装 Git创建 Git 本地仓库配置 Git认识工作区、暂存区、版本库添加文件修改文件版本回退撤销修改删除文件 版本控制器 在日常工作和学习中&#xff0c;老板/老师要求我们修改文档&#xff0c;…

Live800:客户服务新纪元,从响应到主动关怀的转型之路

在当今这个快速变化的商业环境中&#xff0c;客户服务已不再是简单的售后响应或问题解决的环节&#xff0c;而是企业赢得市场、构建品牌忠诚度、实现可持续增长的核心驱动力。随着技术的飞速发展和消费者需求的日益多样化&#xff0c;客户服务正步入一个新的纪元——从传统的被…

电脑上如何多开微信软件(多个微信同时使用)

想登录几个就下面这种文件里&#xff0c;复制几行即可&#xff1a; 创建的是以 .bat 文件结尾的txt文件&#xff08;先创建一个txt文本文档&#xff0c;等写好了命令保存后&#xff0c;再把文件的后缀名改为: .bat &#xff09;再保存即可。然后&#xff0c;右键以管理员运行&a…

电子废物检测回收系统源码分享

电子废物检测回收检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…