当前位置: 首页 > news >正文

多态示例。

多态

由于派生类重写基类方法,然后用基类引用指向派生类对象,调用方法时候会进行动态绑定,这就是多态。 多态分为静态多态和动态多态:

静态多态:编译器在编译期间完成的,编译器会根据实参类型来推断该调用哪个函数,如果有对应的函数,就调用,没有则在编译时报错。

动态多态:其实要实现动态多态,需要几个条件——即动态绑定条件:

  1. 虚函数。基类中必须有虚函数,在派生类中必须重写虚函数。

  2. 通过基类类型的指针或引用来调用虚函数。

说到这,得插播一条概念:重写——也就是基类中有一个虚函数,而在派生类中也要重写一个原型(返回值、名字、参数)都相同的虚函数。不过协变例外。协变是重写的特例,基类中返回值是基类类型的引用或指针,在派生类中,返回值为派生类类型的引用或指针。

函数重载:不依赖继承,解决 “同功能不同类型的调用简化”;
• 动态多态:依赖继承,解决 “基类接口与派生类实现的适配”;
• 协变:依赖继承,解决 “重写时返回值类型的灵活性问题”,是动态多态的补充。
最终目的都是在保证逻辑清晰的前提下,减少冗余代码,提升代码的可维护性和扩展性

1. 函数重载(静态多态)

特点
  • 无需继承,同一类内或全局作用域中定义;
  • 编译时根据参数类型自动匹配函数(静态绑定)。
代码示例
#include <iostream>
using namespace std;// 同一作用域下的函数重载(参数类型不同)
class Calculator {
public:// 重载1:int类型相加int add(int a, int b) {return a + b;}// 重载2:double类型相加(与重载1参数类型不同)double add(double a, double b) {return a + b;}
};int main() {Calculator calc;// 编译时确定调用哪个add(根据实参类型)cout << calc.add(10, 20) << endl;      // 匹配int版本(输出30)cout << calc.add(3.14, 2.5) << endl;   // 匹配double版本(输出5.64)return 0;
}

2. 动态多态

特点
  • 依赖继承,基类需定义虚函数(virtual);
  • 派生类必须 “重写” 虚函数(函数名、参数、返回值完全相同);
  • 通过基类指针 / 引用调用,运行时根据实际对象类型确定调用版本(动态绑定)。
代码示例
#include <iostream>
using namespace std;// 基类(含虚函数)
class Base {
public:// 虚函数:允许派生类重写virtual void show() {cout << "Base类的show方法" << endl;}
};// 派生类(重写基类虚函数)
class Derived : public Base {
public:// 重写:函数名、参数、返回值与基类虚函数完全一致void show() override {  // override可显式标记重写(可选)cout << "Derived类的show方法" << endl;}
};int main() {Derived d;           // 派生类对象Base* base_ptr = &d; // 基类指针指向派生类对象(关键条件)// 运行时动态绑定:调用派生类的show(而非基类)base_ptr->show();  // 输出:Derived类的show方法return 0;
}

3. 协变(重写特例)

特点
  • 属于动态多态的特殊情况,本质是 “合法的重写”;
  • 唯一区别:返回值可以不同,但必须满足 “基类返回基类指针 / 引用,派生类返回派生类指针 / 引用”。
#include <iostream>
using namespace std;// 基类
class Base {
public:// 虚函数:返回Base*virtual Base* getObject() {cout << "返回Base类对象指针" << endl;return this;}
};// 派生类
class Derived : public Base {
public:// 协变重写:返回Derived*(基类返回Base*的派生类型)Derived* getObject() override {  // 符合协变规则,属于合法重写cout << "返回Derived类对象指针" << endl;return this;}
};int main() {Derived d;Base* base_ptr = &d;  // 基类指针指向派生类对象// 运行时动态绑定:调用派生类的getObjectbase_ptr->getObject();  // 输出:返回Derived类对象指针return 0;
}

http://www.lryc.cn/news/603489.html

相关文章:

  • kotlin使用mybatis plus lambdaQuery报错
  • XtestRunner一个比较好用好看的生成测试报告的工具
  • 系统间复制文档
  • 论文阅读--射频电源在半导体领域的应用
  • React--》实现 PDF 文件的预览操作
  • 配置daemon.json使得 Docker 容器能够使用服务器GPU【验证成功】
  • VitePress学习笔记
  • 彻底清理ArcGIS 10.2残留的步骤
  • Windows使用Powershell自动安装SqlServer2025服务器与SSMS管理工具
  • Vue.js 完全指南:从入门到精通
  • getgff.py脚本-python006
  • openbmc 阈值sensor分析
  • 计算机视觉(CV方向)算法基础
  • SketchUp纹理贴图插件Architextures安装使用图文教程
  • Linux sshfs 安全挂载远程文件系统 命令详解
  • Angular面试题目和答案大全
  • AR辅助前端设计:虚实融合场景下的设备维修指引界面开发实践
  • Mac m系列芯片安装node14版本使用nvm + Rosetta 2
  • YotoR模型:Transformer与YOLO新结合,打造“又快又准”的目标检测模型
  • VUE -- 基础知识讲解(一)
  • 【MySQL】数据库的简单介绍
  • Node.js 内置模块
  • 安卓模拟器 adb Frida hook 抓包
  • uniapp如何封装uni.request 全局使用
  • 自适应双门限的能量检测算法
  • 2025年中科院1区SCI-冬虫夏草优化算法Caterpillar Fungus Optimizer-附Matlab免费代码
  • 09 RK3568 Debian11 ES8388 模拟音频输出
  • 电磁兼容(EMC):整改案例(十三)屏蔽外壳开孔解决433MHz无线通信问题
  • vue3+vite 使用liveplayer加载视频
  • 【学习路线】游戏开发大师之路:从编程基础到独立游戏制作