【C++】一文简练总结【多态】及其底层原理&具体应用(21)

前言

大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁
主要内容含:
在这里插入图片描述

欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!

目录

  • 一.多态的概念
  • 二.多态的实现
    • 1)虚函数&虚函数表
    • 2)虚函数的重写(覆盖)
    • 3)多态的构成条件
    • 4)虚函数重写的两种特殊情况:
        • 【1】协变:(基类与派生类虚函数返回值类型不同)
        • 【2】析构函数的重写:(基类与派生类析构函数的名字不同)
  • 三.【override】【final】关键字——帮助用户检测是否重写(C++11)
      • 【1】 final:表示虚函数不能被重写,被重写即报错
      • 【2】override:检查虚函数是否重写了别的虚函数,重写了即报错
  • 四. 多态的具体应用:抽象类(接口类)(纯虚函数类)
      • 1)利用 [ 只有重写纯虚函数 派生类才能实例化出对象 ] 性质
      • 2)实现继承与接口继承

一.多态的概念

  • 多态是在不同继承关系的类对象,去调用 同一 函数,产生了 不同 的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。
  • 例:iphone和安卓手机用户打车同程不同价

二.多态的实现

1)虚函数&虚函数表

  • 虚函数:即被 virtual 修饰的类成员函数称为虚函数。
class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl;}
};
  • 虚函数表本质是一个存虚函数指针 指针数组,一般情况这个数组最后面放了一个nullptr。
  • 虚函数表:虚函数表存的是虚函数指针,不是虚函数,虚函数和普通函数一样的,都是存在代码段的,只是他的指针又存到了虚函数表中。
  • 一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表

2)虚函数的重写(覆盖)

  • 虚函数的重写(覆盖): 派生类中有一个跟基类完全相同的虚函数 (即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同) ,称子类的虚函数 重写 了基类的虚函数。

3)多态的构成条件

  1. 必须通过 基类的指针 引用 调用虚函数
  2. 被调用的函数 必须是虚函数,且 派生类必须对基类的虚函数进行重写
                                           //多态条件2:被调用的函数 必须是虚函数
class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:                                   //多态条件2:派生类必须对基类的虚函数进行重写virtual void BuyTicket() { cout << "买票-半价" << endl; }
/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因
为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议
这样使用*/
/*void BuyTicket() { cout << "买票-半价" << endl; }*/
};void Func(Person& p)       //多态条件1:必须通过基类的指针来“引用”调用虚函数
{ 
p.BuyTicket(); 
}int main()
{
Person ps;
Student st;
Func(ps);
Func(st);return 0;
}

4)虚函数重写的两种特殊情况:

【1】协变:(基类与派生类虚函数返回值类型不同)
  • 派生类重写基类虚函数时 ,与基类虚函数 返回值类型不同 。即如下代码所示:【基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时】,称为协变
class A{};
class B : public A {};
class Person {
public:virtual A* f() {return new A;}
};
class Student : public Person {
public:virtual B* f() {return new B;}
};
【2】析构函数的重写:(基类与派生类析构函数的名字不同)
  • 如果 基类的析构函数为虚函数 ,此时派生类析构函数只要定义, 无论是否加virtual关键字
    都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。 虽然函数名不相同【~Person() 】 【~Student() 】,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成 destructor
class Person {
public:                  //基类的析构函数为虚函数virtual ~Person() {cout << "~Person()" << endl;}
};class Student : public Person {
public://~Student() { cout << "~Student()" << endl; 不加virtual也行virtual ~Student() { cout << "~Student()" << endl; }
};
// 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函数,
//才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数。
int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0;
}

三.【override】【final】关键字——帮助用户检测是否重写(C++11)

  • 从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数
    名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有
    得到预期结果才来debug会得不偿失,因此:C++11从两个角度提供了 override final 两个关键字,可以帮
    助用户检测是否重写。
  • final:表示虚函数不能被重写,被重写即报错
  • override:检查虚函数是否重写了别的虚函数,重写了即报错

【1】 final:表示虚函数不能被重写,被重写即报错

class Car
{
public:virtual void Drive() final {}
};
class Benz :public Car
{
public:virtual void Drive() {cout << "Benz-舒适" << endl;}
};

【2】override:检查虚函数是否重写了别的虚函数,重写了即报错

class Car{
public:virtual void Drive(){}
};
class Benz :public Car {
public:virtual void Drive() override {cout << "Benz-舒适" << endl;}
};

四. 多态的具体应用:抽象类(接口类)(纯虚函数类)

1)利用 [ 只有重写纯虚函数 派生类才能实例化出对象 ] 性质

  • 在虚函数的后面写上 =0 ,则这个函数为 纯虚函数 包含纯虚函数的类 叫做 抽象类(也叫接口类) [ 抽象类不能实例化出对象 ]&[ 派生类继承后也不能实例化出对象 ] 只有 [ 重写纯虚函数 ] ,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
class Car
{
public:
virtual void Drive() = 0;         //在虚函数的后面写上 =0,这个函数为 纯虚函数
};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();
}

2)实现继承与接口继承

  • 普通函数的继承是一种 实现继承 ,派生类继承了基类函数,可以使用函数,继承的是函数的实现。
  • 虚函数的继承是一种 接口继承 ,派生类继承的是基类虚函数的接口, 目的是为了重写,达成多态 ,继承的是接口。所以如果不实现多态,不要把函数定义成虚函数。

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

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

相关文章

【C++】:拷贝构造函数与赋值运算符重载的实例应用之日期类的实现

C实现日期类 ├─属性&#xff1a; │ ├─年份 │ ├─月份 │ └─日期 ├─方法&#xff1a; │ ├─构造函数 │ ├─拷贝构造函数 │ ├─析构函数 │ ├─设置年份 │ ├─设置月份 │ ├─设置日期 │ ├─获取年份 │ ├─获取月份 │ ├─获取日期 │ ├…

websocket和mqtt

WebSocket是一种通信协议&#xff0c;它允许在浏览器和服务器之间建立持久连接&#xff0c;并允许双向传递数据。MQTT则是一种轻量级的发布/订阅消息传输协议&#xff0c;常用于物联网(IoT)设备之间的通信。 &#xff08;1&#xff09;js能直接实现mqtt吗&#xff0c;还是需…

已解决java.lang.IllegalStateException: Duplicate key

已解决java.lang.IllegalStateException: Duplicate key 文章目录 报错问题解决思路解决方法交流 报错问题 java.lang.IllegalStateException: Duplicate key 解决思路 java.lang.IllegalStateException: Duplicate key 是由于在使用 Map 或 Set 时&#xff0c;试图将一个已经…

十、sdl显示yuv图片

前言 SDL中内置加载BMP的API&#xff0c;使用起来会更加简单&#xff0c;便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片&#xff0c;可以使用第三方库&#xff1a;SDL_image 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…

redis的性能管理和雪崩

redis的性能管理 redis的数据是缓存在内存当中的 系统巡检&#xff1a; 硬件巡检、数据库、nginx、redis、docker、k8s 运维人员必须要关注的redis指标 在日常巡检中需要经常查看这些指标使用情况 info memory #查看redis使用内存的指标 used_memory:11285512 #数据占用的…

最简单的简历练习

代码&#xff1a; <!DOCTYPE html> <html> <head> <title>我的简历</title> <style> body { background-image: url(https://picsum.photos/id/1018/1000/1000); background-size: cover; …

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法,亲测有效!!!

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录 报错问题解决方法交流 报错问题 java.lang.RuntimeException: java.io.IOException: invalid cons…

完美解决ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python36\pyt

完美解决ERROR: Command errored out with exit status 1: command: f:\program files\python\python36\pyt 下滑查看解决方法 文章目录 报错问题解决思路解决方法交流 报错问题 ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python3…

【华为OD】C卷真题 100%通过:攀登者1 C/C++源码实现

【华为OD】C卷真题 100%通过&#xff1a;攀登者1 C/C源码实现 目录 题目描述&#xff1a; 示例1 代码实现&#xff1a; 题目描述&#xff1a; 攀登者喜欢寻找各种地图&#xff0c;并且尝试攀登到最高的山峰。 地图表示为一维数组&#xff0c;数组的索引代表水平位置&…

C++二分查找算法:有序矩阵中的第 k 个最小数组和

本文涉及的基础知识点 二分查找算法合集 本题的简化 C二分查找算法&#xff1a;查找和最小的 K 对数字 十分接近m恒等于2 题目 给你一个 m * n 的矩阵 mat&#xff0c;以及一个整数 k &#xff0c;矩阵中的每一行都以非递减的顺序排列。 你可以从每一行中选出 1 个元素形成…

哈希unordered_set,unordered_map的练习

349. 两个数组的交集 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2]示例 2&#xff1a; 输…

JSP过滤器和监听器

什么是过滤器 Servlet过滤器与Servlet十分相似&#xff0c;但它具有拦截客户端&#xff08;浏览器&#xff09;请求的功能&#xff0c;Servlet过滤器可以改变请求中的内容&#xff0c;来满足实际开发中的需要。 对于程序开发人员而言&#xff0c;过滤器实质就是在Web应用服务器…

使用Wireshark提取流量中图片方法

0.前言 记得一次CTF当中有一题是给了一个pcapng格式的流量包&#xff0c;flag好像在某个响应中的图片里。比较简单&#xff0c;后来也遇到过类似的情况&#xff0c;所以总结和记录一下使用Wireshark提取图片的方法。 提取的前提是HTTP协议&#xff0c;至于HTTPS的协议需要导入服…

【算法】摩尔投票算法

目录 1.概述2.算法思想3.代码实现3.1.t ⌊n / 2⌋3.2.t ⌊n / 3⌋3.3.t ⌊n / (m 1)⌋ 4.应用 参考&#xff1a;LeetCode_多数元素 II 题解 1.概述 &#xff08;1&#xff09;摩尔投票法 (Boyer–Moore Majority Vote Algorithm) 是一种用来寻找一组元素中多数元素的常量级…

flutter,uni-app开发调试ios

一、申请ios开发者账号 二、ios开发者配置 ios 开发者需要配置的地方 https://developer.apple.com/account/resources/certificates/list Certificates&#xff08;证书&#xff09;: 作用&#xff1a; 证书用于对应用程序和开发者进行身份验证&#xff0c;确保安全性和可…

如何为您的企业选择合适的多因素认证?

在传统的网络安全架构中&#xff0c;重点在于防止非法入侵&#xff0c;例如防火墙、VPN 、堡垒机等安全设备的重心都在于防止用户违规访问企业资源&#xff0c;一旦合法用户的账号密码被入侵者拿到&#xff0c;就可以冒充合法用户访问企业资源&#xff0c;所有的安全设备形同虚…

springcloud超市管理系统源码

技术说明&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;idea&#xff0c;vscode springcloud springboot mybatis vue elementui mysql 功能介绍&#xff1a; 后台管理&#xff1a; 统计分析&#xff1a;查看用户&#xff0c;商品&#xff0c;销售数量&#xff1b;…

Mock 数据

1. Mock 数据的方式 2. json-server 实现 Mock 数据 项目中安装json-server npm i -D json-server准备一个json文件添加启动命令 //package.json"scripts": {"start": "craco start","build": "craco build","test&q…

简单聊聊加密和加签的关系与区别

大家好&#xff0c;我是G探险者。 平时我们在项目上一定都听过加密和加签&#xff0c;加密可能都好理解&#xff0c;知道它是保障的数据的机密性&#xff0c;那加签是为了保障啥勒&#xff1f;它和加密有啥区别&#xff1f; 带着这个疑问&#xff0c;我们就来聊聊二者的区别。…

SHEIN出口车钥匙扣REACH认证指南解析

钥匙扣的材料一般为金属、皮革、塑料、橡胶、木头等。此物精致小巧、造型千变万化是人们随身携带的日常用品。钥匙扣是挂在钥匙圈上的一种装饰物品。钥匙扣出口需要办理REACH认证。 一、什么是REACH认证&#xff1f; REACH认证是欧盟28个成员国对进入其市场的所有化学品,&…