C++多态讲解

news/2024/9/18 6:13:26/ 标签: c++, 后端

在这里插入图片描述

多态


多态的概念

通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态)这里重点讲运行时多态。

运行时多态

运行时多态,具体点就是去完成某个行为(函数),可以传不同的对象就会完成不同的行为,就达到多种形态。

多态的定义以及实现

多态的构成条件

多态是一个继承关系的下的类对象,去调用同一函数,产生了不同的行为。

  • 实现多态的两个必须的重要条件

    • 必须指针或者引用调用虚函数。

    • 被调用的函数必须是虚函数。

    • 总结:要实现多态效果,第一必须是基类的指针或引用,因为只有基类的指针或引用才能既指向派生类对象;第二派生类必须对基类的虚函数重写/覆盖,重写或者覆盖了,派生类才能有不同的函数,多态的不同形态效果才能达到。

  • 虚函数

    类成员函数前面加 virtual 修饰,那么这个成员函数被称为虚函数。注意非成员函数不能加 virtual 修饰。

      class Person{public:virtual void print(){cout << "Hello world" << endl;}};
    

  • 虚函数的覆盖和重写

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

    • 注意:在重写基类虚函数时,派生类的虚函数在不加 virtual 关键字时,虽然也可以构成重写,但是该种写法不是很规范,不建议这样使用。

    • 代码示例:

    #include <iostream>using namespace std;// 多态class Person{public:virtual void print() // 2.必须使用虚函数,并且虚函数完成了重写或者覆盖。这里的virtual不可以去掉{cout << "Person" << endl;}};class Student : public Person{public:// 派生类的虚函数可以不加virtualvirtual void print() // 2.使用虚函数,并且虚函数完成了重写或者覆盖。这里的virtual可以去掉{cout << "Student" << endl;}};void Func(Person *ptr) // 1.必须是基类的指针或者引用{ptr->print();}int main(){Person s1;Student s2;Func(&s1);Func(&s2);}
    

  • 关于多态的选择题

    以下程序输出结果为:
    A:A->0 B:B->1 C:A->1 D:B->0 E:编译出错 F:以上都不正确

        class A{public:virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }virtual void test() { func(); }};class B : public A{public:void func(int val = 0) { std::cout << "B->" << val << std::endl; }};int main(int argc, char *argv[]){B *p = new B;p->test();return 0;}
    
    • 解析:
      答案为:B


      这里发生了重写,就相当于将基类的 virtual void func(int val = 1) 替换到了派生类的 void func(int val = 0)

  • 虚构函数的其他问题

    • 协变

      派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。

      #include <iostream>
      using namespace std;class A
      {
      };
      class B : public A
      {
      };
      class Person
      {
      public:virtual A *BuyTicket(){cout << "买票-全价" << endl;return nullptr;}
      };
      class Student : public Person
      {
      public:virtual B *BuyTicket(){cout << "买票-打折" << endl;return nullptr;}
      };
      void Func(Person *ptr)
      {ptr->BuyTicket();
      }
      int main()
      {Person ps;Student st;Func(&ps);Func(&st);return 0;
      }
      
    • 析构函数的重写

      基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加 virtual 关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同看起来不符合重写的规则,实际上编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成 destructor,所以基类的析构函数加了 vialtual 修饰,派生类的析构函数就构成重写。


  • 重载/重写/隐藏的对比
    请添加图片描述

纯虚函数和抽象类

在虚函数的后面写上 =0 ,则这个函数为纯虚函数,纯虚函数不需要定义实现(实现没啥意义因为要被派生类重写,但是语法上可以实现),只要声明即可。包含纯虚函数的类叫做抽象类,抽象类不能实例化出对象,如果派生类继承后不重写纯虚函数那么派生类也是抽象类。纯虚函数某种程度上强制了派生类重写虚函数,因为不重写实例化不出对象。


在这里插入图片描述


http://www.ppmy.cn/news/1526040.html

相关文章

Spring事务传播行为详解

在Spring框架中&#xff0c;事务管理是一个至关重要的部分&#xff0c;它确保了数据的一致性和完整性。Spring提供了灵活的事务传播行为&#xff0c;允许开发者根据具体场景选择不同的事务管理方式。本文将详细介绍Spring的七种事务传播行为&#xff0c;并通过示例代码来展示它…

RTCP协议

一、常用RTCP数据包类型 类型缩写表示解释200SR&#xff08;Sender Report&#xff09;发送端报告201RR&#xff08;Receiver Report&#xff09;接收端报告202SDES&#xff08;Source Description Items&#xff09;源点描述203BYE结束传输204APP特定应用 &#xff08;一般&a…

Acwing 区间合并

区间合并 主要思想&#xff1a;给定很多区间。若两个区间有交集&#xff0c;将二者合并成一个区间。 具体做法: 先按照区间的左端点进行排序然后遍历每个区间&#xff0c;根据不同的情况进行合并&#xff0c;有一下几种情况&#xff1a; 第一种情况&#xff0c;区间不变&…

【Scala入门学习】Scala的方法和函数

1. 方法 在scala中的操作符都被当成方法存在&#xff0c;比如说、-、*、/ 12就是1.(2)的调用&#xff0c; 2.0 是doule类型&#xff0c;强调用Int类型的写法为1.(2:Int) 1.1 方法的声明和使用 定义方法的语法&#xff1a; def 方法名([变量&#xff1a;变量类型&#xff…

C++竞赛初阶L1-15-第六单元-多维数组(34~35课)556: T456506 矩阵转置

题目内容 输入一个 n 行 m 列的矩阵 A,输出它的转置 AT。 输入格式 第一行包含两个整数 n 和 m,表示矩阵 A 的行数和列数。1≤n≤100,1≤m≤100。 接下来 n 行,每行 m 个整数,表示矩阵 A 的元素。相邻两个整数之间用单个空格隔开,每个元素均在 1∼1000 之间。 输出格…

移动订货小程序哪个好 批发订货系统源码哪个好

订货小程序就是依托微信小程序的订货系统&#xff0c;微信小程序订货系统相较于其他终端的订货方式&#xff0c;能够更快进入商城&#xff0c;对经销商而言更为方便。今天&#xff0c;我们一起盘点三个主流的移动订货小程序&#xff0c;看看哪个移动订货小程序好。 第一、核货宝…

【MyBatis---快速学习和复习】

学习视频&#xff08;强推&#xff09;&#xff1a;【MyBatis视频零基础入门到进阶&#xff0c;MyBatis全套视频教程源码级深入详解】 https://www.bilibili.com/video/BV1JP4y1Z73S/?p134&share_sourcecopy_web&vd_source4d877b7310d01a59f27364f1080e3382 MyBatis中…

Go语言错误处理详解

Go语言以其简洁、高效和并发能力著称。在实际开发中&#xff0c;错误处理是一个不可避免且至关重要的部分。本文将深入探讨Go语言中的错误处理机制&#xff0c;涵盖其原理、使用方法、最佳实践&#xff0c;并提供丰富的代码示例和中文注释。 一、错误处理的基本概念 在Go语言…

STL02——手写简单版本的list

手写一个简单版本的list 设计一个名为 List 的 List 类&#xff0c;该类具有以下功能和特性&#xff1a; 1、基础成员函数 构造函数&#xff1a;初始化 List 实例析构函数&#xff1a;清理资源&#xff0c;确保无内存泄露 2、核心功能 在 List 末尾添加元素在 List 开头添…

【Gateway】网关服务快速上手

微服务的接口都是直接对外暴露的,可以直接通过外部访问,为了保证对外服务的安全性服务端实现的微服务接口通常都带有一定的权限校验机制,由于使用了微服务,原本一个应用的的多个模块拆分成了多个应用,我们不得不实现多次校验逻辑,当这套逻辑需要修改时,我们需要修改多个应用,加…

数据脱敏 (Jackson + Hutool 工具包)

一、简介 系统使用 Jackson 序列化策略&#xff0c;对标注了 Sensitive 注解的属性进行脱敏处理 基于Hutool 脱敏案列&#xff1a; Retention(RetentionPolicy.RUNTIME) Target(ElementType.FIELD) JacksonAnnotationsInside// 表示只对有此注解的字段进行序列化 JsonSeriali…

【超详细】Plaxis软件简介、 Plaxis Python API环境搭建、自动化建模、Python全自动实现、典型岩土工程案例实践应用

查看原文>>>【案例教程】PLAXIS软件丨自动化建模、典型岩土工程案例解析、模型应用、数据分析、图表制作 目录 第一部分&#xff1a;Plaxis软件简介及 Plaxis Python API环境搭建 第二部分&#xff1a;Plaxis自动化建模-基础案例 第三部分&#xff1a;进阶案例-Pyt…

neo4j docker 运行4.35 community 版本失败

运行脚本 sudo docker run -d \ --name container_name \ -p 27474:7474 \ -p 27687:7687 \ -v /home/neo4j/data:/data \ -v /home/neo4j/logs:/logs \ -v /home/neo4j/conf:/var/lib/neo4j/conf \ -v /home/neo4j/import:/var/lib/neo4j/import \ -v /home/lighthouse/tcmkg…

redis常见的数据类型?

参考&#xff1a;一文读懂Redis五种数据类型及应用场景 - 知乎 (zhihu.com) String 类型 String 类型&#xff1a;Redis 最基本的数据类型&#xff0c;它是二进制安全的&#xff0c;意味着你可以用它来存储任何类型的数据&#xff0c;如图片、序列化对象等。使用场景&#xff…

智慧交通基于yolov8的行人车辆检测计数系统python源码+onnx模型+精美GUI界面

【算法介绍】 智慧交通中&#xff0c;基于YOLOv8的行人车辆检测计数系统是一项高效、准确的技术解决方案。该系统利用YOLOv8这一先进的目标检测算法&#xff0c;结合深度学习技术&#xff0c;能够实时检测并准确计数道路上的行人和车辆。YOLOv8在保证检测速度的同时&#xff0…

SprinBoot+Vue爱老助老服务平台的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

oracle 表的外键

表的外键 3.5.1表之间的三种关系 在数据库设计中&#xff0c;工作中经常会分析商业逻辑中的表的设计。在设计表的关系之前&#xff0c;需要先了解关系型数据库特点。关系数据库有如下特点&#xff1a; 关系型数据库采用了关系模型来组织数据的数据库。 关系型数据库的最大特点…

C#笔记11 获取线程及其信息,什么是优先级、单元状态、线程状态、执行状态、线程名称以及其他属性?

前文讲完了在C#中线程怎么创建&#xff0c;怎么删除&#xff0c;怎么启动&#xff0c;怎么阻止。 现在来看看线程本身的属性。 当前线程 首先要获得当前线程&#xff0c;才能获取线程信息&#xff0c;此属性用于获取当前运行的线程。此属性可用于获取代码当前执行所在的线程…

qt下两种方式读取opencv 图片各个通道的值

qt下两种方式读取opencv 图片各个通道的值 Mat srcImg imread("D:\\1.jpg");if(srcImg.empty()){QMessageBox::information(this,"警告","图片读取失败&#xff0c;请检查图片路径&#xff01;");return;}Mat imgShow ;cvtColor(srcImg, imgSho…

企微机器人:企业数字化转型的得力助手

在数字化转型的浪潮中&#xff0c;企业对于提高运营效率、降低人力成本的需求日益迫切。企微机器人&#xff0c;作为基于企业微信平台开发的一种智能工具&#xff0c;以其高度自动化、灵活性强、安全性高和易于使用的特点&#xff0c;迅速成为企业内部的得力助手。本文将深入探…