C++中的四种多态 (The Four Polymorphisms in C++翻译)

Oracle数据库RMAN异机恢复保姆级教程,按照步骤来操作,一次就成功! 本文深入解析RMAN异机恢复四大核心场景(演练、数据恢复、故障应急、测试环境搭建),提供从备份到验证的完整步骤和实战脚本。包含RAC到单机迁移技巧、路径调整、常见报错解决方案,助你彻底掌握数据库恢复的“救命技能”。DBA必备干货,强烈推荐 阅读详情

本文为The Four Polymorphisms in C++这篇文章的翻译,非机器翻译,如有理解或术语错误望指正,谢谢~

C++中的四种多态(Polymorphisms)

当人们在谈论C++的多态的时候,他们通常指的是通过基类的指针或者引用,来使用派生类,这其实被称为子类型多态(subtype polymorphism),但是他们经常会忘掉其实C++里面还有各种其他的多态,比如参数多态(parametric polymorphism),重载多态(ad-hoc polymorphism)和强制多态(coercion polymorphism)。

这些多态在C++中也有其他不同的名称:

  • 子类型多态也被称为运行时多态(runtime polymorphism)。
  • 参数多态也被称为编译时多态(compile-time polymorphism)。
  • 重载多态也被称为重载(overloading)。
  • 强制多态也被称为**(显式的或隐式的)类型转换(casting)**。

我将在这篇文章里通过例子来说明C++中的所有多态,并告诉你为什么它们有这样的名字。

子类型多态(运行时多态)

子类型多态是人们在说C++多态时所能理解的那种,它可以通过基类的指针或者引用来使用派生类。

举个例子,假设你有各种的猫科动物,
在这里插入图片描述由于他们都属于猫科生物家族,所以他们都可以发出类似喵的叫声(原文是they all should be able to meow),这样他们都可以通过继承猫科动物Felid这个基类来表示,并重写meow这个纯虚函数。

// file cats.h

class Felid {
public:
 virtual void meow() = 0;
};

class Cat : public Felid {
public:
 void meow() { std::cout << "Meowing like a regular cat! meow!\n"; }
};

class Tiger : public Felid {
public:
 void meow() { std::cout << "Meowing like a tiger! MREOWWW!\n"; }
};

class Ocelot : public Felid {
public:
 void meow() { std::cout << "Meowing like an ocelot! mews!\n"; }
};

现在主程序可以通过Felid基类指针使用Cat,Tiger和Ocelot类,

#include <iostream>
#include "cats.h"

void do_meowing(Felid *cat) {
 cat->meow();
}

int main() {
 Cat cat;
 Tiger tiger;
 Ocelot ocelot;

 do_meowing(&cat);
 do_meowing(&tiger);
 do_meowing(&ocelot);
}

主程序向do_meowing这个函数传递了指向cat, tiger和ocelot的指针,而这个函数期望一个指向Felid对象的指针。因为cat, tiger和ocelot都属于Felid,程序可以为每个猫科动物调用正确的meow函数,并且输出如下:

Meowing like a regular cat! meow!
Meowing like a tiger! MREOWWW!
Meowing like an ocelot! mews!

子类型多态也被叫作运行时多态,因为,多态函数调用的解析发生在运行时,并通过虚表间接完成。另一种解释方式是,编译器不能在编译期定位函数被调用的地址,而在程序运行时,通过取消引用虚表的右指针来调用函数。

在类型理论中这也被成为包含多态性。

参数多态(编译时多态)

参数多态提供了一种可以对任何类型数据执行相同代码的方法。在C++里,参数多态通过模板(template)来实现。

一个最简单的例子就是max函数,它用来寻找传入的两个参数的最大值,

#include <iostream>
#include <string>

template <class T>
T max(T a, T b) {
 return a > b ? a : b;
}

int main() {
 std::cout << ::max(9, 5) << std::endl;     // 9

 std::string foo("foo"), bar("bar");
 std::cout << ::max(foo, bar) << std::endl; // "foo"
}

这里max函数在类型T上就是参数多态的,但是如果参数类型是指针那就不行了,因为比较指针相当于比较内存地址,而不是指针指向的内容。如果想要能比较指针指向的内容,就必须专门再设计一个指针类型的模板,那样的话其实就不再是参数多态了,而是重载多态。

因为参数多态发生在编译时,所以它也被称为编译时多态。

重载多态(重载)

重载多态可以允许函数拥有相同的函数名而对不同的类型的数据执行不同的动作。比如,给两个int数据和+号,加号会把他们加在一起。给两个字符串std::string,加号会把他们连接在一起,这就叫重载。

下面给出一个实现对int类型和string类型相加的具体例子,

#include <iostream>
#include <string>

int add(int a, int b) {
 return a + b;
}

std::string add(const char *a, const char *b) {
 std::string result(a);
 result += b;
 return result;
}

int main() {
 std::cout << add(5, 9) << std::endl;
 std::cout << add("hello ", "world") << std::endl;
}

如果专门设定模板里的类型,那也是重载多态,回到我们之前的例子,下面的代码展示了如何写一个max函数来比较两个char *指针,

template <>
const char *max(const char *a, const char *b) {
 return strcmp(a, b) > 0 ? a : b;
}

现在你可以调用::max("foo", "bar")来寻找字符串"foo"和"bar"的最大者。

强制多态(类型转换)

强制多态发生在一个对象或者基本数据类型的数据转换成另外一种对象类型或基本数据类型时。比如,

float b = 6; // int 隐式地转换成 float
int a = 9.99 // float 隐式地转成 int

显示类型转换发生在你使用C风格的类型转换表达式比如(unsigned int *), (int)或者C++的static_cast, const_cast, reinterpret_cast或者dynamic_cast。

强制多态也会发生在非显式调用类的构造函数时,例如,

#include <iostream>

class A {
 int foo;
public:
 A(int ffoo) : foo(ffoo) {}
 void giggidy() { std::cout << foo << std::endl; }
};

void moo(A a) {
 a.giggidy();
}

int main() {
 moo(55);     // prints 55
 // 译者注:传进去了55数字,但是隐式地调用了A类的构造函数,发生了int-> A的类型转换
}

如果你显示调用了A的构造函数,那就不会发生强制多态了,显示的调用类的构造函数总是比较好的,可以避免意外的转换。

此外,如果一个类定义了对类型T的转换操作符,那么这个类的对象可以用在任何需要使用类型T的地方。

比如,

class CrazyInt {
 int v;
public:
 CrazyInt(int i) : v(i) {}
 operator int() const { return v; } // conversion from CrazyInt to int
};

CrazyInt定义了转换为int类型的转换操作符,如果你有一个函数,比如print_int,需要传入一个int的参数,我们也可以直接把CrazyInt类型的对象传进去,

#include <iostream>

void print_int(int a) {
 std::cout << a << std::endl;
}

int main() {
 CrazyInt b = 55;
 print_int(999);    // prints 999
 print_int(b);      // prints 55
 // 译者注:传进去b对象,隐式地转换成了int数字
}

前面讲到的子类型多态实际上也是强制多态,因为他是把派生类转换成了基类。

RT-DETR改进策略【损失函数篇】| 通过辅助边界框计算IoU提升检测效果(Inner_GIoU、Inner_DIoU、Inner_CIoU、Inner_EIoU、Inner_SIoU) 为了弥补现有 IoU 损失在不同检测任务中泛化性弱和收敛速度慢的问题,·Inner-IoU·通过引入比例因子 “ratio” 来控制辅助边界框的尺度大小,利用不同尺度的辅助边界框来计算损失,从而加速边界框回归过程。 阅读详情

相关推荐

开题报告该怎么写

考研即将来临,而一般很多大学都会选择在考研结束之后开始安排选题和开题报考(考研之前一般都不谈,老师也很人性化的,不愿意耽误你的复习) 但无论怎么推迟,我们最终都需要去面对并完成这些任务。 现在我就要教大家该如何写一个完整的开题报告! 准备模板。不同的学校有不同的格式,一般情况你的导师会给你们一个学校的标准格式,这个不用太费心。有了模板我们就可以按照模板的“线索”一步一步填充完成即可! 一般大致格式可谓: 研究背景/论文的目的、背景和意义 我们需要写明选择该题目的...

wuyueweifeng的博客 1095

四十四、多态性:多态的概念和类型

1、多态的类型 四种:重载多态、强制多态、参数多态、包含多态 前面两种为专用多态。普通函数和类成员函数的重载,属于重载多态。再如整形变量和浮点变量相加,整形会转换为浮点进行运算,这就是强制多态。 后面两种为参数多态。如模板类型参数化就是参数多态。包含多态一般通过虚函数实现。   2、多态实现 编译时多态:编译时确定具体调用哪个函数。即 静态绑定、(重载,强制,参数多态都是静态绑定

lsfreeing的专栏 2062

【无机纳米材料科研制图——OriginLab 0205】Origin对BET吸附/脱附曲线及孔径分布制图...

此篇,我们来分享如何对BET数据进行处理和制图。 一、等温吸脱附曲线绘制 1)找到等温吸脱附文件。 一半来说,对一个样品测一次BET,会产生很多数据,具体因仪器而异。我这里的数据主要有两个文件夹,一个脱附,一个吸附,吸附文件夹中多了一个等温吸脱附的文件夹。而这...

XD_Yangf的博客 803

多态的表现形式

多态有四种体现形式: 1. 接口和接口的继承。 2. 类和类的继承。 3. 重载。 4. 重写。 其中重载和重写为核心。 重载:重载发生在同一个类中,在该类中如果存在多个同名方法,但是方法的参数类型和个数不一样,那么说明该方法被重载了。 重写:重写发生在子类继承父类的关系中,父类中的方法被子类继承,方法名,返回值类型,参数完全一样,但是方法体不一样,那么说明父类中的该方法被子类重写了。 ...

Arvin_SC的博客 6499

Unity Shader Graph 2D - Procedural程序化图形转动的环状六边形

Hexagon又称六边形,在游戏中是十分常见的基础形状,本文将使用程序化的六边形来制作多个环状六边形叠加的转动动画效果,实践Unity Shader Graph中的常用节点功能。

Giver的博客 1928

以太网硬件核心:MAC、PHY、MII与交换机原理与实战排查

计算机网络通信的基础依赖于一套完整的硬件协议栈。在OSI模型中,数据链路层和物理层是实现设备间可靠、高效数据传输的基石。其核心原理在于将上层数据包封装成帧,并通过特定的介质访问控制与物理信号转换机制进行传输。这一过程的技术价值在于为上层应用提供了透明、稳定的通信信道,是互联网和所有局域网通信的物理承载。在嵌入式系统、网络设备开发及运维等应用场景中,深入理解底层硬件交互至关重要。本文将聚焦于以太网硬件的两大核心组件:负责逻辑成帧与流量控制的MAC控制器,以及负责数模转换与链路协商的PHY芯片。它们通过MII、

dgqvhtlwq472235338的博客 420

多态的四种不同形式

在收到消息时,对象要予以响应。不同的对象收到同一消息可以产生完全不同的结果,这一现象称为多态。在使用多态的时候,用户可以发送一个通用的消息,而实现的细节由接收对象自行决定。这样,同一消息就可以调用不同的方法。多态的实现受到继承的支持,利用类继承的层次关系,把具有通用功能的消息存 放在高层次,而不同的实现这一功能的行为放在较低层次,在这些低层次的对象能够给通用消息以不同的响应。

当他回首往事时,不应为虚度年华而后悔,也不会因为碌碌无为而羞耻。 1万+

雷达气象学(8)——反射率因子图实战(强对流预警篇)

本文聚焦雷达反射率因子图在强对流预警中的实战应用,深入解析了柱状回波、有界弱回波区(BWER)、三体散射(TBSS)等关键回波结构特征,这些是识别超级单体风暴和大冰雹的核心“身份证”。文章强调从静态识别转向动态追踪与多源数据综合研判的思维转变,并提供了系统的实战分析流程与常见误区避坑指南,旨在提升对强对流天气的短临预警能力。

weixin_29213827的博客 485

编译期多态和运行期多态

       运行期多态(runtime polymorphism),也称为显式多态,是指类中成员函数是virtual,类将对这些函数表现出运行期多态,也就是说将于运行期根据基类指针或者引用的动态类型决定究竟调用哪一个函数。        编译期多态(cmpile-time polymorphisms),也称为隐式多态,是指以不同的template参数具现化function templates ...

kang___xi的博客 1375

vue3接入大华摄像头

┃ ┃ ┣ 📜PlaybackModal.vue 回放列表模态框。┃ ┃ ┗ 📜VideoGrid.vue 视频播放区域。┃ ┃ ┣ 📜ControlPanel.vue 控制面板。┃ ┃ ┣ 📜DeviceList.vue 设备列表。┃ ┣ 📂module //大华摄像头文件。

💻 专注 Vue 前端与 Java 后端技术 🌱 目前正在深入 Spring Boot、微服务与性能优化 📝 定期分享实战踩坑经验与学习笔记 🤝 欢迎交流,共同进步 913

工业级Modbus ASCII实时监控系统(WinForms完整实现)

本文介绍了一个基于WinForms的工业级Modbus ASCII实时监控系统实现方案。该系统采用经典工控界面布局,包含串口配置、数据采集控制和实时数据显示三大区域。核心功能包括:串口通信参数设置、Modbus从站地址配置、寄存器数据采集、实时数据表格展示和趋势图绘制。系统通过ModbusAsciiClient类实现通信核心,采用定时器轮询机制采集数据,支持最多100个数据点的历史趋势显示。界面设计注重用户体验,配置区位于左侧,主显示区在右侧,底部为状态和日志区,符合工业控制系统的操作习惯。代码示例展示了窗

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 277

C++中的四种多态

本文转载自The Four Polymorphisms in C++

ccf19881030的专栏 2290

蓝鸟四轴飞控系统C程序V3.0(基础版本)深度解读

2. 解析遥控通道数据(油门 / 横滚 / 俯仰 / 偏航),转换为标准化值(-1000~+1000);3. 封装PID初始化(PID_Init,配置KP/KI/KD、输出限幅、积分限幅);,包含姿态角(Attitude_Data.Roll/Pitch/Yaw)、角速度(Gyro_Data.X/Y/Z)、遥控值(RC_Data[0~5])、电池电压(Bat_Volt)、电机PWM值(Motor_PWM[0~3])、系统状态(Sys_State),校验和通过Check_Sum()函数计算;

搏博的专栏 343

C++编程入门系列之四十四(多态性:多态的概念和类型)

上一节讲完赋值兼容规则后,编程入门中继承与派生的部分就讲完了。今天开始讲解面向对象设计中的多态性。        先介绍一个概念:消息。消息在C++编程中指的是对类的成员函数的调用。多态就是指相同的消息被不同类型的对象接收会引起不同的操作,直接点讲,就是在不同的情况下调用同名函数时,可能实际调用的并不是同一个函数。        以“+”运算符为例,“+”可以实现整型变量之间、浮点型变

赵小咖的博客 1066

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C++虚函数与多态实现

虚函数实现 虚函数的发明初衷在于使得程序具有更好的通用性,从代码编写的角度看,其使用基类的指针指向子类的对象,并调用虚函数,使得根据指向的对象 而调用不同的子类函数,从而实现运行时多态(Runtime polymorphism),这个特性与c语言中的函数指针回调非常相似,在c语言中,我们将函数指针作为参数传递给其他函数,然后调用,根据其指向的不同函数而产生不同的行为,c代码示例如下 #include <stdio.h> typedef void(*func)(void); void foo(

New life 1423

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

多态的四种实现

静态多态: 1.强制多态(强制类型转换) 2.过载多态(函数重载,运算符重载) 3.参数多态(类模板,函数,模板) 动态动态: 4.包含多态(虚函数) ...

m0_37313888的博客 1024

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

多态

体现:父类引用变量可以指向子类对象 前提:必须有子父类关系或者类实现接口关系,否则无法完成多态 使用多态后的父类引用变量调用方法时,会调用子类重写后的方法 多态的定义与使用格式: 父类类型/接口类型 变量名 = new 子类类型(); 变量名.方法名(); 多态成员变量: 当子父类中出现同名的成员变量时,多态调用该变量时: 编译时期:参考的是引用型变量所属的类中是否有被调用的成员...

gorgeoustudy的博客 171

为什么说重写是运行时多态?

为什么说重写是运行时多态?

XRT_knives的博客 578

C++的多态(polymorphism)

基本定义:在C++中,多态(polymorphism)是一种面向对象编程(OOP)的特性,允许不同的类(通常是基类和派生类)使用相同的接口进行交互,但表现出不同的行为。

choose_heart的博客 376

多态性说明

你了解多态性吗?

weixin_45217447的博客 594

【面向对象】多态的四种形式(重载、改写、多态变量、泛型)

多态可以分为重载、改写、多态变量、泛型四种形式。 1、 重载(Overload) 是在一个类里面,方法名字相同,而参数(个数或者类型)不同。 通俗来讲,就是两个函数名相同而类型签名不同,他们之间构成重载关系。 但是要注意的是:返回类型可以相同也可以不同,即返回类型不能作为重载函数的区分。 示例代码: A、public void function (**int a**) {…}; B、public ...

SDUzzy的博客 2857

C++ 中的多态性 (polymorphism) - Polymorphism in C++

C++ 中的多态性 (polymorphism) - Polymorphism in C++ ->Function Overloading (函数重载) ->编译时多态 (Compile time Polymorphism)-> ->Operator Over

程永强 1720

编译时多态和运行时多态,方法重载和方法重写

通常用于在同一个类中提供多种方式的功能,以提高代码的可读性和易用性。重载方法与访问权限,异常无关。

m0_68773076的博客 716

Java面试题每日10问(7)

Java面试题每日10问(7)

weixin_45428910的博客 481

C++多态之四种实现形式

多态性的四种实现形式,分别是强制多态、重载多态、类型参数化多态、包含多态。

LWD的博客 5550

C++高级面试题:解释 C++ 中的编译时多态性(Compile-Time Polymorphism)。

因此,我们在编译时就可以确定要调用的具体函数版本,实现了编译时多态性。函数重载是一种静态多态性,因为在编译时就确定了调用的函数版本。函数模板(Function Templates):函数模板允许在编写函数时使用参数的通用类型,从而在编译时生成多个具体的函数版本。函数模板也是一种静态多态性。在这两种情况下,编译器根据函数调用的上下文和传递的参数类型,在编译时就能够确定调用的具体函数版本,因此称为编译时多态性。这种多态性的优势在于性能更高,因为函数调用的解析在编译时完成,不需要在运行时再进行函数查找和绑定。

qiuyehuanghun的博客 629
上一篇: python IO编程知识点
下一篇: python魔术方法(dunder method)__len__, __getitem__, __repr__等
Guuuuuu老师儿
博客等级 码龄9年 259粉丝 718原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值