C++ DAY06 c++多态

简介

一个事物的多种形态 , 简称多态
物的多态
同一个人在不同人面前展现是不同的
:
        在我面前
        在对象面前
        在朋友面前
        在父母面前
事的多态
吃饭
        中国人 筷子 熟食
        美国人 刀叉 7 分熟
        日本人 筷子 生食
        印度人 手
睡觉
        中国人 床上
        日本人 榻榻米
        侧卧
        平躺
        趴着

上行与下行

上行

子类转父类
语法
        父类名 * 父类对象指针 = 子类对象指针 ;
        父类名& 父类对象名 = 子类对象 ;
注意 :
        无风险, 无需强转

下行

父类转换为子类
语法
        子类名 * 子类对象指针 = ( 子类名 *) 父类对象指针 ;
        子类名& 子类对象 = ( 子类名 &) 父类对象 ;
注意 :
        有风险, 需强转

重写

重载

        同一作用域下, 函数名形同相同 ,形参列表不同        

重定义

        函数继承时,继承关系中,函数名相同即可

重写

        继承关系中,返回值类型相同,函数名形同,形参列表相同,函数体不同

c++多态分类

静态多态 ( 早绑定 , 静态联编 )
        概念:在编译阶段 就确定函数的入口地址.
        又名: 静态联编 , 早绑定
        如: 函数重载 , 运算符重载 , 重定义等
动态多态 ( 晚绑定 , 动态联编 )
        概念: 在运行阶段确定程序入口地址
        又名: 动态联编 , 晚绑定
        如: 虚函数 , 重写

引入

要求 : 设计一个函数 , 根据传入的对象调用重写的方式
代码
#include <iostream>
using namespace std;
class Anim{
public:void test01(){cout << "动物test01" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{
a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}
运行结果
原因
        父类指针只能操作子类空间中的父类部分。

虚函数

概念

        virtual修饰的成员函数 , 就是虚函数

语法    

virtual 返回值类型 函数名 ( 形参列表 )
{
        方法体
}

特点

当子类转换为父类后
使用该父类调用使用 virtual 修饰的函数 , 调用的是子类重写后的
使用该父类调用普通函数 , 调用的是父类的该函数

补充概念

重写 : 在继承关系中 , 子类方法与父类方法 , 返回值类型一致 , 函数名相同 , 形参列表相同
注意 : 子类重写父类虚函数 , 子类该函数默认为虚函数

代码

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01(){cout << "动物test01" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}

动态绑定条件(重要)

有继承,子类重写父类的虚函数,父类指针或引用指向子类空间。父类指针或引用才能调用子类重写的虚函数。
错误演示
        B b;
        //此时会调用父类的拷贝构造 , 会产生一个新的父类对象 , 该父类对象 a 与子类对象b是两个独立空间 ,所以此时使用a 对象调用 test01 依据会执行父类的 test01 函数
        //A a = b;
        A& a = b;
        a.test01();

动态绑定原理(重要)

父类有虚函数,产生虚函数指针指向虚函数表,表中纪录的是父类的虚函数地址。
如果子类继承父类,那么子类会继承父类的虚函数指针以及虚函数表。
如果子类重写父类的虚函数,会将将虚函数表纪录的入口地址修改成子类重写的函数入口地址。
这时父类指针指向子类空间,父类指针调用虚函数就间接调用子类重写的虚函数。

纯虚函数

概念

        父类的虚函数没有函数体

语法

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

示例

#include <iostream>
using namespace std;
class Anim{
public:
//纯虚函数virtual void test01() = 0;
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}

注意

纯虚函数所在的类不能直接创建对象 , 这种类被称为抽象类
子类继承与抽象类 , 要么重写父类提供的所有纯虚函数 , 要么自己也是抽象类

虚析函数

引入

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}~Anim(){cout << "父类析构" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果

        问题: 没有子类析构函数调用
        解决方案: 将父类的析构函数 设置成 虚析构

语法

virtual ~ 析构函数 ()
{
}

代码

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}virtual ~Anim(){cout << "父类析构" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果:

纯虚析构(了解)

语法

        virtual 析构函数名 () = 0;

注意

        需要在类外实现析构函数

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}virtual ~Anim() = 0;
};
Anim::~Anim()
{cout << "父类析构" << endl;
}
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果

总结

1、虚函数和纯虚函数的区别?
        虚函数和纯虚函数都是为了通过父类指针调用子类重写的虚函数。
        虚函数 不=0 修饰 , 有函数体 , 所在的类不是抽象类 , 可以实例化对象。
        纯虚函数 =0 修饰 , 没有函数体 , 所在的类是抽象类 , 不可以实例化对象。
2、虚析构和纯虚析构的区别
        虚析构和纯虚析构都是为了通过父类指针释放子类的所有空间( 父类部分 , 子类部分 )
        虚析构不=0 修饰 , 所在的类不是抽象类 , 可以实例化对象。
        纯虚析构=0 修饰 , 类外实现函数体 , 所在的类是抽象类 , 不可以实例化对象。
3、重载、重定义、重写的区别
        重载:没有继承,函数重载和运算符重载。函数名相同,参数的个数,顺序、类型可以不同,返回值类型不能作为重载条件。
        重定义:有继承,子类重定义父类同名函数(非虚函数)。返回值类型,形参可以相同 和 不同。
        重写:有继承,子类重写父类的虚函数。函数名,返回值类型,形参必须和父类同名函数一致。

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

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

相关文章

参数估计(一)(点估计)

文章目录 点估计和估计量的求法点估计概念矩估计法极大似然估计法 参考文献 参数估计是数理统计中重要的基本问题之一。通常&#xff0c;称参数的可容许值的全体为参数空间&#xff0c;并记为 Θ \Theta Θ。所谓参数估计就是由样本对总体分布所含的未知参数做出估计。另外&am…

个人博客汇总

博客汇总 建设完成的博客建设中的博客规划建设的博客看过但是暂时不会整理的博客 建设完成的博客 建设中的博客 集体智慧编程 redis设计与实现 GRPC 规划建设的博客 书籍类 DDIA 技术方案 活动增长裂变增长裂变人群打标 看过但是暂时不会整理的博客 刑法学讲义蛤蟆先生去…

MyBatis 操作数据库(构造动态 SQL)

前言 动态 SQL 是 Mybatis 的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接。 <if> 标签 我们在填写用户信息的时候经常会看到如下的界面&#xff0c;用户信息中包含必填信息和非必填信息&#xff0c;非必填信息是填和不填都可以的&#xff0c;那这样的话…

基本算法:二分

文章目录 1、整数集合上的二分2、实数域上的二分3、三分求单峰函数极值4、二分答案转化为判定二分的基础用法是在单调序列或单调函数中进行查找。因此,当问题的答案具有单调性时,就可以通过二分把求解转化为判定(根据复杂度理论,判定的难度小于求解),这使得二分的运用范围…

IDEA常用插件合集

功能类&#xff1a; 1、Background Image Plus 换壁纸 2、Chinese(Simplified)... 中文语言包 3、Translation 代码翻译 4、Key Promoter X 快捷键提示插件 5、Rainbow bracket 彩虹括号插件&#xff0c;对于多组括号使用不同的颜色标注 6、Code Glance 代码小地图&a…

参加了南京 GDG 活动:这些精彩的技术讨论,值得与你分享~

一直以来发的文章大都是技术的&#xff0c;这次和大家聊点简单点的。 密集输出这几年&#xff0c;因为疫情没能在线下和大家碰面&#xff0c;去年又因为时间原因浪费了 Google IO China 门票。所以&#xff0c;今年的南京本地的 GDG DevFest 2023 活动一经上线&#xff0c;就报…

国际物流社交销售玩法拆解(三):打造社交电商式分销增长

这一篇&#xff0c;是国际物流行业社交销售玩法最后一篇&#xff0c;也是国际物流企业实现业务经营新增长、打造分销增长体系的新模式。以下&#xff0c;我们一起来拆解这一模式具体内容吧。 #01 国际物流第二曲线&#xff1a;社交电商 经营增长是企业的永恒话题。在客户成本…

C++多线程编程(3):接收线程处理函数的返回值

文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 文章目录 处理带返回值的函数asyncpackaged_taskpromise 处理带返回值的函数 有三种方法&#xff1a; asyncpackaged_taskpromise async 第一种方法是使用 async 函数。 步骤&#xff1a; 使用 async 创建线程处理函…

16. @PostConstruct注解和开关原理(验证码开关、IP开关)

1►PostConstruct注解 PostConstruct是java自带的注解&#xff0c;会在java项目启动的时候先执行下面的方法 2►开关原理&#xff08;验证码开关&#xff09; 我们的项目具有验证码功能&#xff0c;旧版不支持关闭&#xff0c;新版已经支持关闭了。 我们打开页面“参数管…

Python Web APP在宝塔发布

本地测试运行&#xff1a;uvicorn main:app --host 127.0.0.1 --port 8082 --reload 宝塔发布&#xff1a; 运行配置——>启动模式&#xff1a;worker_class uvicorn.workers.UvicornWorker

【STL】:反向迭代器

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关反向迭代器的模拟实现&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

rabbitMQ的direct模式的生产者与消费者使用案例

消费者C1的RoutingKey 规则按照info warn 两种RoutingKey匹配 绑定队列console package com.esint.rabbitmq.work03;import com.esint.rabbitmq.RabbitMQUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DeliverCallback;/*** 消费者01的消息接受*/ p…

如何使用MybatisPlus进行数据分页显示

如何使用MybatisPlus进行数据的分页呢&#xff1f; 使用Mybatis Plus提供的分页插件来简化开发&#xff0c;在MybatisPlusInterceptor的拦截器中添加自动分页的PaginationInnerInterceptor拦截器&#xff0c;当前配置需要交给spring的bean管理&#xff0c;类上添加注解Configu…

目标检测 Faster RCNN全面解读复现

Faster RCNN 解读 经过R-CNN和Fast RCNN的积淀&#xff0c;Ross B. Girshick在2016年提出了新的Faster RCNN&#xff0c;在结构上&#xff0c;Faster RCNN已经将特征抽取(feature extraction)&#xff0c;proposal提取&#xff0c;bounding box regression(rect refine)&…

php聊天室通讯系统常用的接口对接函数 curl、file_get_contents()、WebSocket、消息队列

方法有&#xff1a; 1、HTTP请求&#xff0c;可以通过PHP的curl库或者file_get_contents()函数发送HTTP请求来与聊天室接口进行通信&#xff1b; 2、WebSocket协议&#xff0c;可以使用PHP的WebSocket库或者第三方库来与聊天室接口进行对接&#xff1b; 3、使用这些SDK或者包装…

GIT提交代码

1、从远端克隆master分支 git clone -b master ssh://git*** 2、创建开发分支 git checkout -b 209192_dev 3、在对应分支下更新代码 -f为强制更新&#xff0c;会覆盖本地 git pull -f origin 209192_dev:209192_dev git pull -f origin sit:sit git pull -f origin uat:uat 4、…

Nginx快速入门教程,域名转发、负载均衡

1.Nginx简介 Nginx是⽬前最流⾏的Web服务器&#xff0c; 最开始是由⼀个叫做igor的俄罗斯的程序员开发的&#xff0c; 2019年3⽉11⽇被美国的F5公司以6.7亿美元的价格收购&#xff0c; 现在Nginx是F5公司旗下的⼀款产品了。 2.Nginx的版本 Nginx开源版本主要分为两种&#x…

21、嵌套路由实战操作

1、创建内嵌子路由&#xff0c;你需要添加一个vue文件&#xff0c;同时添加一个与该文件同名的目录用来存放子视图组件。 2、在父组件&#xff08;.vue&#xff09;内增加用于显示子视图内容 新建文件 pages\index_id.vue 生成的对应路由 {path: "/",component: _…

电子病历编辑器源码(Springboot+原生HTML)

一、系统简介 本系统主要面向医院医生、护士&#xff0c;提供对住院病人的电子病历书写、保存、修改、打印等功能。本系统基于云端SaaS服务方式&#xff0c;通过浏览器方式访问和使用系统功能&#xff0c;提供电子病历在线制作、管理和使用的一体化电子病历解决方案&#xff0c…

产品经理不得不知道的电商API接口对接流程梳理

接口对接流程梳理 产品经理 知晓自己负责系统做什么&#xff0c;外接三方系统做什么。 系统对接产品经理实操步骤&#xff1a; ①与公司业务人员沟通&#xff0c;与系统对接方产品/技术描述业务场景&#xff0c;沟通发放接口文档材料 ②拿到材料之后电商API接口过多请对方…