C++中多态的使用和建立条件

一、多态引入

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

根据代码,引入多态的概念:

#include <iostream>
using namespace std;//定义一个成人类
class Person {
public:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};//定义一个学生类
class Student : public Person {
public:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person& p)
{p.BuyTicket();
}
int main()
{Person ps;  //成人对象Student st; //学生Func(ps);  // void Func(Person& p) 参数传参,函数调用Func(st);  // void Func(Person& p) 参数传参,函数调用return 0;
}

在这里插入图片描述
执行结果可以看出根据对象的不同,调用出来不同的结果

多态的概念:通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态 。

修改上面的代码,观察结果:
#include <iostream>
using namespace std;class Person {
public://修改前:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public://修改前:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person& p)
{p.BuyTicket();
}
int main()
{Person ps;Student st;Func(ps);Func(st);return 0;
}

在这里插入图片描述
我们去掉virtual 关键字之后,看到结果都是调用父类的BuyTicket()函数。 原因分析:student类继承person类,两个类里面的BuyTicket()函数函数名一样,构成重定义(1.函数名相同 2.两个函数分别在父子类的作用域里 3. 父子类的同名函数不构成重写),所以子类对象赋值给父类对象的时候,会将子类对象中的父类切出来,自然而然调用的是父类的成员函数

我们再修改代码,思考结果:
#include <iostream>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person p)  //修改前:Person& p
{p.BuyTicket();
}
int main()
{Person ps;Student st;Func(ps);Func(st);return 0;
}

在这里插入图片描述
这个结果的产生原因和上面的原因是一致的,父类赋值给父类对象自然调用父类的成员函数、子类对象赋值给父类对象造成“切片”,将子类中的父类那一部分切出去,让父类对象调用

再修改代码,看结果:
#include <iostream>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person* p)  //修改前:Person& p
{p->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);  //修改前 Func(ps);Func(&st);  //修改前 Func(st);return 0;
}

在这里插入图片描述

使用指针的时候又根据指向对象的不同,调用出不同的结果

根据上面的代码结果,我们可以大概感知到多态就是根据不同继承关系的类对象,调用同一函数时产生了不同的行为。那么产生多态的条件是什么呢?


文章目录

  • 一、多态引入
        • 修改上面的代码,观察结果:
        • 我们再修改代码,思考结果:
        • 再修改代码,看结果:
  • 二、多态构成的条件
        • 回顾上面的代码,感受多态的条件
        • 析构函数的重写-析构函数名统一会被处理成destructor()
        • C++11 新语法:override 和 final
        • 抽象类
            • 1、概念
            • 2、 抽象类代码感知
  • 总结


二、多态构成的条件

重写的概念

  • 两个函数分别在子类和父类的作用域中
  • 函数名 / 返回值 / 参数都必须相同
  • 两个函数必须是虚函数 (被virtual 修饰的类成员函数成为虚函数
  • 注意:参数只看类型是否相同,不看缺省值

多态构成的条件

  • 需要在继承中使用
  • 必须使用父类的引用或者指针调用虚函数
  • 被调用的函数必须是虚函数,且子类必须对父类的虚函数进行重写
回顾上面的代码,感受多态的条件
#include <iostream>
using namespace std;
class Person {
public://父类的虚函数virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public://子类 重写 父类的虚函数(重写:函数名、返回值、参数必须相同)virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person* p)
{p->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);Func(&st);return 0;
}

这时候指针p,它指向什么类型,就调用该类型的对象里面的成员

在这里插入图片描述

析构函数的重写-析构函数名统一会被处理成destructor()

只有子类 Student 的析构函数重写了 Person 的析构函数,下面的 delete 对象调用析构函
数,才能构成多态,才能保证 p1 和 p2 指向的对象正确的调用析构函数。
函数名处理成destructor() 才能满足多态:
如果父类的析构函数为虚函数,此时子类析构函数只要定义,无论是否加virtual关键字,
都与父类的析构函数构成重写,虽然父类与子类析构函数名字不同。虽然函数名不相同,
看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处
理,编译后析构函数的名称统一处理成destructor。

class Person {
public:virtual ~Person() {cout << "~Person()" << endl;}
};
class Student : public Person {
public:virtual ~Student() { cout << "~Student()" << endl; }
};
int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0; 
}

在这里插入图片描述
所以当父类的指针指向子类的对象时,一定需要将父类的析构函数写成虚函数,如果不定义成虚函数,那么delete p的时候,就会只父类的析构函数(切片),不会调用子类的析构函数,造成内存泄漏

C++11 新语法:override 和 final

final:修饰虚函数,表示该虚函数不能再被重写

在这里插入图片描述

override: 检查子类虚函数是否重写了父类某个虚函数,如果没有重写编译报错

在这里插入图片描述

抽象类
1、概念

在虚函数的后面写上 “= 0” ,则这个函数为纯虚函数包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象子类继承后也不能实例化出对象,只有重写纯虚函数,子类才能实例化出对象。纯虚函数规范了子类必须重写,另外纯虚函数更体现出了接口继承。
在这里插入图片描述

2、 抽象类代码感知
#include <iostream>
using namespace std;class Car
{
public:virtual void Drive() = 0;//	// 实现没有价值,因为没有对象会调用他//	/*virtual void Drive() = 0//	{//		cout << " Drive()" << endl;//	}*/
};
class Benz :public Car
{
public:virtual void Drive()  //重写父类的纯虚函数{cout << "Benz-舒适" << endl;}
};
class BMW :public Car
{
public:virtual void Drive() //重写父类的纯虚函数{cout << "BMW-操控" << endl; }
};
void Test()
{Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();
}
int main()
{Test();return 0;
}

在这里插入图片描述


总结

今天我们熟悉了多态的构成条件以及多态的使用,下一次我们详细聊聊多态的原理,感知一下为什么会出现这样的结果?编译器是怎么做得?

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

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

相关文章

【计算机毕设选题推荐】图书在线商城SpringBoot+SSM+Vue

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot的图书在线商城 技术栈 SpringBootVueMySQLMaven 文章目录 一、图书在线商城…

[ Windows ] ping IP + Port 测试 ip 和 端口是否通畅

开发过程中经常会黑窗口中手动测试一下计划请求的目标ip和端口是否通畅&#xff0c;测试方式如下&#xff1a; 一、单纯测试ip是否能够 ping 通&#xff0c;这个比较熟悉了&#xff0c;运行 cmd 打开黑窗口 输入如下指令&#xff0c;能够如下提示信息&#xff0c;表示端口是通…

Cloud Studio连接MySQL,Access denied for一系列问题

官方文档有写如何安装Mysql $ apt update $ apt install mysql-server mysql-client -y$ service mysql start mysql -uroot -p123456进入MySQL命令行 问题出在连接数据库这一步&#xff0c;命令行能进去&#xff0c;但是数据库插件和代码都连不上 Access denied for 大概率…

35 机器学习(三):混淆矩阵|朴素贝叶斯|决策树|随机森林

文章目录 分类模型的评估混淆矩阵精确率和召回率 接口介绍其他的补充 朴素贝叶斯基础原理介绍拉普拉斯平滑下面给出应用的例子朴素贝叶斯的思辨 决策树基础使用基本原理信息熵信息增益信息增益率Gini指数 剪枝api介绍 随机森林------集成学习初识基本使用api介绍 分类模型的评估…

音频录制和处理软件 Audio Hijack mac中文版说明

Audio Hijack mac是一款功能强大的音频录制和处理软件&#xff0c;它可以帮助用户从各种来源捕获和处理音频。 首先&#xff0c;Audio Hijack具有灵活的音频捕获功能。它支持从多个来源录制音频&#xff0c;包括麦克风、应用程序、网络流媒体、硬件设备等等。你可以选择捕获整个…

告别传统纸质期刊,电子期刊更环保更快捷

​【新发现】随着科技的发展&#xff0c;电子期刊逐渐取代了传统的纸质期刊&#xff0c;成为人们获取信息的新选择。电子期刊不仅环保&#xff0c;而且快捷方便&#xff0c;但是你知道怎么制作电子期刊吗&#xff1f; 不会制作的可以试试我推荐的这个网站----FLBOOK电子杂志制作…

无代码玩转web UI自动化

可以直接进入官网下载开源版或点击右上角体验企业版体验 RunnerGo UI自动化平台 RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度…

报错:AttributeError: module ‘tensorflow‘ has no attribute ‘flags‘

改成如下&#xff1a; 报错原因&#xff1a;tensorflow1.x与2.x版本问题不兼容

今日最新版早安问候大全,秋天早上好祝福短句,生活顺心,一切开心

天上最美的是星星&#xff0c;关心朋友的是短信&#xff0c;人间最美的是真情&#xff0c;外表留给人的是印象&#xff0c;内心留给人的是感情&#xff0c;珍惜了今天你就拥有了明天&#xff0c;愿你开怀地笑&#xff0c;温柔地睡&#xff01;早安朋友&#xff01; 早晨的阳光…

Leetcode——数组的旋转

189. 轮转数组 class Solution { public:void rotate(vector<int>& nums, int k) {int lennums.size();vector<int> num(len);for(int i0;i<len;i){num[(ik)%len]nums[i];}nums.assign(num.begin(),num.end());} };旋转数组 没看出数学公式gg 正确答案 cl…

AI大模型高速发展,Web3还远吗?

在过去的几年里&#xff0c;人工智能&#xff08;AI&#xff09;和Web3技术都经历了令人瞩目的发展。AI大模型&#xff0c;特别是像GPT-3、GPT-4等这样的巨型语言模型&#xff0c;已经成为AI领域的明星&#xff0c;而Web3则代表了下一代互联网的愿景&#xff0c;具有去中心化和…

最近邻插值的原理及实现

1. 介绍 插值算法一般用来做上采样和下采样,最邻近插值算法,是插值算法中最简单的一种。 最邻近插值:将每个目标像素找到距离它最近的原图像素点,然后将该像素的值直接赋值给目标像素。 优点: 实现简单,计算速度快 缺点:插值结果缺乏连续性,可能会产生锯齿状的边缘,对…

scratch时间游戏 2023年9月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析

目录 scratch时间游戏 一、题目要求 1、准备工作 2、功能实现 二、案例分析

Cocos Creator3.8 项目实战(十)使用 protobuf详细教程

在 Cocos Creator 中使用 protobuf.js 库可以方便地进行协议的序列化和反序列化。 下面是使用 protobuf.js 的详细说明&#xff1a; 一、protobuf环境安装 1、安装 npm protobuf环境安装安装需要使用 npm 命令进行&#xff0c;因此首先需要安装 npm 。 如果你还没安装 npm …

微信一键群发超过200人的方法

在当前社交媒体的大潮中&#xff0c;微信已跻身全球最热门的社交平台之列。对于企业的运营管理来说&#xff0c;微信的管理系统工具发挥着举足轻重的作用。然而&#xff0c;微信自带的群发助手功能最多只能发送消息给200个好友&#xff0c;要是需要发送1000个好友甚至更多&…

《论文阅读28》OGMM

一、论文 研究领域&#xff1a; 点云配准 | 有监督 部分重叠论文&#xff1a;Overlap-guided Gaussian Mixture Models for Point Cloud Registration WACV 2023 二、概述 概率3D点云配准方法在克服噪声、异常值和密度变化方面表现出有竞争力的性能。本文将点云对的配准问题…

10款远程办公软件,助你事半功倍,晋升快如闪电

选择一个易于使用和方便的远程软件&#xff0c;可以提高团队的整体效率&#xff0c;减少加班&#xff0c;使整个团队更受益。互联网行业从产品经理、UI/从UX设计师到技术开发和测试人员&#xff0c;每一个环节都需要密切沟通和跟踪&#xff0c;在远程沟通中及时发现问题&#x…

power point导出pdf保留字体

在 slides 中用到非自带的字体&#xff0c;如 [1]&#xff0c;想导出成 pdf 文件&#xff08;因为导出成图&#xff0c;如 png&#xff0c;放大会蒙&#xff09;&#xff0c;并在别人电脑里也保留字体。除了让别人也装上相应字体&#xff0c;可以&#xff1a; 参考 [2]&#x…

“岗课赛证”融通的物联网综合实训室建设方案

一、概述 随着5G技术的普及应用和产业经济的革新发展,物联网产业所呈现的广阔前景带来了对创新型技术技能人才的迫切需求。高职院校物联网专业建设也因此转变为面向国家战略性新兴产业发展需求。当前,“岗位课程竞赛证书”融通的培育理念,是高职院校物联网人才培养和专业优化的…

Anomalib 图像异常检测算法

图像异常检测算法 1.简介1.1. 问题描述1.2. 挑战与需求 2. 图像异常检测定义2.1 异常的定义及类型2.2 图像数据中的异常 3. 图像异常检测技术研究现状4.方法5.安装和使用5.1 安装PyPI 安装本地安装 5.2 训练5.3 特征提取与&#xff08;预训练&#xff09;backones5.4 自定义数据…