1. C++ 编译期多态与运行期多态

C++ 编译期多态与运行期多态

今日的C++不再是个单纯的“带类的C”语言,它已经发展成为一个多种次语言所组成的语言集合,其中泛型编程与基于它的STL是C++发展中最为出彩的那部分。在面向对象C++编程中,多态是OO三大特性之一,这种多态称为运行期多态,也称为动态多态;在泛型编程中,多态基于template(模板)的具现化与函数的重载解析,这种多态在编译期进行,因此称为编译期多态或静态多态。在本文中,我们将了解:

  • 什么是运行期多态
  • 什么是编译期多态
  • 它们的优缺点在哪
运行期多态

运行期多态的设计思想要归结到类继承体系的设计上去。对于有相关功能的对象集合,我们总希望能够抽象出它们共有的功能集合,在基类中将这些功能声明为虚接口(虚函数),然后由子类继承基类去重写这些虚接口,以实现子类特有的具体功能。典型地我们会举下面这个例子:

图片

class Animal
{
public :virtual void shout() = 0;
};
class Dog :public Animal
{
public:virtual void shout(){ cout << "汪汪!"<<endl; }
};
class Cat :public Animal
{
public:virtual void shout(){ cout << "喵喵~"<<endl; }
};
class Bird : public Animal
{
public:virtual void shout(){ cout << "叽喳!"<<endl; }
};int main()
{Animal * anim1 = new Dog;Animal * anim2 = new Cat;Animal * anim3 = new Bird;//藉由指针(或引用)调用的接口,在运行期确定指针(或引用)所指对象的真正类型,调用该类型对应的接口anim1->shout();anim2->shout();anim3->shout();//delete 对象...return 0;
}

运行期多态的实现依赖于虚函数机制当某个类声明了虚函数时,编译器将为该类对象安插一个虚函数表指针,并为该类设置一张唯一的虚函数表,虚函数表中存放的是该类虚函数地址。运行期间通过虚函数表指针与虚函数表去确定该类虚函数的真正实现

运行期多态的优势还在于它使处理异质对象集合称为可能:

//我们有个动物园,里面有一堆动物
int main()
{vector<Animal*>anims;Animal * anim1 = new Dog;Animal * anim2 = new Cat;Animal * anim3 = new Bird;Animal * anim4 = new Dog;Animal * anim5 = new Cat;Animal * anim6 = new Bird;//处理异质类集合anims.push_back(anim1);anims.push_back(anim2);anims.push_back(anim3);anims.push_back(anim4);anims.push_back(anim5);anims.push_back(anim6);for (auto & i : anims){i->shout();}//delete对象//...return 0;
}

总结:运行期多态通过虚函数发生于运行期

编译期多态

对模板参数而言,多态是通过模板具现化和函数重载解析实现的。以不同的模板参数具现化导致调用不同的函数,这就是所谓的编译期多态。
相比较于运行期多态,实现编译期多态的类之间并不需要成为一个继承体系,它们之间可以没有什么关系,但约束是它们都有相同的隐式接口。我们将上面的例子改写为:

class Animal
{
public :void shout() { cout << "发出动物的叫声" << endl; };
};
class Dog
{
public:void shout(){ cout << "汪汪!"<<endl; }
};
class Cat
{
public:void shout(){ cout << "喵喵~"<<endl; }
};
class Bird
{
public:void shout(){ cout << "叽喳!"<<endl; }
};
template <typename T>
void  animalShout(T & t)
{t.shout();
}
int main()
{Animal anim;Dog dog;Cat cat;Bird bird;animalShout(anim);animalShout(dog);animalShout(cat);animalShout(bird);getchar();
}

在编译之前,函数模板中t.shout()调用的是哪个接口并不确定。在编译期间,编译器推断出模板参数,因此确定调用的shout是哪个具体类型的接口。不同的推断结果调用不同的函数,这就是编译器多态。这类似于重载函数在编译器进行推导,以确定哪一个函数被调用。

运行期多态与编译期多态优缺点分析
运行期多态优点
  • OO设计中重要的特性,对客观世界直觉认识。

  • 能够处理同一个继承体系下的异质类集合。

运行期多态缺点
  • 运行期间进行虚函数绑定,提高了程序运行开销。
  • 庞大的类继承层次,对接口的修改易影响类继承层次。
  • 由于虚函数在运行期在确定,所以编译器无法对虚函数进行优化。

虚表指针增大了对象体积,类也多了一张虚函数表,当然,这是理所应当值得付出的资源消耗,列为缺点有点勉强。

编译期多态优点
  • 它带来了泛型编程的概念,使得C++拥有泛型编程与STL这样的强大武器。

  • 在编译器完成多态,提高运行期效率。

  • 具有很强的适配性与松耦合性,对于特殊类型可由模板偏特化、全特化来处理。

编译期多态缺点
  • 程序可读性降低,代码调试带来困难。
  • 无法实现模板的分离编译,当工程很大时,编译时间不可小觑。
  • 无法处理异质对象集合。
关于显式接口与隐式接口

所谓的显式接口是指类继承层次中定义的接口或是某个具体类提供的接口,总而言之,我们能够在源代码中找到这个接口。显式接口以函数签名为中心,例如

void AnimalShot(Animal & anim)
{anim.shout();
}

我们称shout为一个显式接口。在运行期多态中的接口皆为显式接口。

而对模板参数而言,接口是隐式的,奠基于有效表达式。例如:

template <typename T>
void AnimalShot(T & anim)
{anim.shout();
}

m)
{
anim.shout();
}


我们称shout为一个显式接口。在运行期多态中的接口皆为显式接口。而对模板参数而言,接口是隐式的,奠基于有效表达式。例如:```c++
template <typename T>
void AnimalShot(T & anim)
{anim.shout();
}

对于anim来说,必须支持哪一种接口,要由模板参数执行于anim身上的操作来决定,在上面这个例子中,T必须支持shout()操作,那么shout就是T的一个隐式接口。

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

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

相关文章

Kubernetes-3

Kubernetes学习第3天 Kubernetes-31、查看实时的cpu和内存消耗1.1、kubectl top node 2、卷的使用2.1、什么是卷&#xff1f;1. 解决数据持久性问题2. Kubernetes 中的卷抽象概念3. 共享数据示例4. Kubernetes 中的卷使用5. 不同类型的卷6. 灵活、可靠的数据管理 2.2、联想到do…

融资项目——通过OpenFeign在分布式微服务框架中实现微服务的远程调用

1.OpenFeign配置 首先&#xff0c;在需要调用其他的微服务的微服务中引入相关依赖。&#xff08;大多数项目中各微服务需要互相调用&#xff0c;可以直接在每个微服务中引入依赖&#xff09; <!--服务调用--><dependency><groupId>org.springframework.clou…

【Memory协议栈】NVRAM Manager 模块介绍

目录​​​​​​​ 前言 正文 1.功能简介 2.关键概念 3.功能详解 3.1 内存硬件抽象层Ea/Fee的寻址方案 3.2 基本存储对象Basic storage objects 3.2.1 NV Block 3.2.2 RAM Block 3.2.3 ROM Block 3.2.4 Administrative block 3.2.5 NV Block Header 3.3块管理类型…

云手机实现全方位的海外舆情监测

近年来&#xff0c;随着各大品牌在海外市场的崛起&#xff0c;海外舆情监测变得尤为重要。企业在拓展国际业务的同时&#xff0c;面临着海外市场的信息难获取、竞争激烈等问题。为解决这一难题&#xff0c;Ogcloud推出的云手机应运而生&#xff0c;为企业提供全方位的海外舆情监…

【软件测试】如何申请专利?

一、专利类型 在软件测试领域&#xff0c;可以申请发明专利、实用新型专利和外观设计专利。其中&#xff0c;发明专利是最常见的专利类型&#xff0c;它保护的是软件测试方法、系统和装置等技术方案。 二、申请专利的条件 申请专利需要满足新颖性、创造性和实用性三个条件。…

PEIS源码 健康体检中心源码 C/S

目录 一、系统概述 二、系统开发环境 三、系统功能 检前管理 检中管理 检后管理 设备对接-PACS 设备对接-彩超 LIS-结果录入、审核、外送结果自动导入 一、系统概述 体检系统&#xff0c;是专为体检中心/医院体检科等体检机构&#xff0c;专门开发的全流程管理系…

HTML5:七天学会基础动画网页9

在进行接下来的了解之前我们先来看一下3d的xyz轴&#xff0c;下面图中中间的平面就相当于电脑屏幕&#xff0c;z轴上是一个近大远小的效果。 3d转换属性 transform 2D或3D转换 transform-origin 改变旋转点位置 transform-style 嵌套元素在3D空间如何显 …

JumpServer 简介安装

目录 1、概念介绍 JumpServer 概述 JumpServer 功能 JumpServer 组件 JumpServer 架构 2、前置安装 环境要求 安装 ELRepo 库 更新内核 设置 grub2 安装 Python 配置 Python 虚拟环境 3、安装 Jumpserver Core 组件 下载安装 替换客户端组件 安装 Python 依赖库…

【Web】浅浅地聊SnakeYaml反序列化两条常见利用链

目录 关于Yaml 关于SnakeYaml SnakeYaml反序列化利用 JdbcRowSetImpl链 ScriptEngineManager链 复现 基本原理 继续深入 关于Yaml 学过SpringBoot开发的师傅都知道&#xff0c;YAML和 Properties 文件都是常见的配置文件格式&#xff0c;用于存储键值对数据。 这里举…

干货分享③:免费制作产品管理系统!

他来了&#xff0c;他来了&#xff0c;他带着码上飞CodeFlying走来了&#xff01;今天继续为大家带来一期干货分享&#xff0c;教大家如何免费使用码上飞来的开发产品管理系统 &#xff01; 一、登陆官网 码上飞 CodeFlying | AI 智能软件开发平台&#xff01; 点击立即体验注…

服务器严重不够啊

必需采购服务器了&#xff0c;

一个比较全面实用的C#帮助类、工具类库

前言 经常会有一些同学会问为什么感觉我身边的大佬写一个功能会这么快&#xff1f;一个类似的模块大佬可能半天就搞定了&#xff0c;而我要搞一两天。其实工作久了你会发现很多常用公共的帮助类和工具类&#xff0c;如常见的Excel数据导入导出、文件操作、字符串操作、数据转换…

从零搭建React18.2+ReactRoute6.22+TS5+RTK2.2搭配antd5+antd-style书写All in Js完整体验项目规范

1. 使用CRA创建项目 全局设置npm淘宝镜像源 npm config set registry https://registry.npmmirror.com -g使用最新版create-react-app初始化项目结构 npx create-react-app custom-template --template typescript初始化项目之后在package.json文件中配置使用node>18.0.0…

WordPress供求插件API文档:用户登录

该文档为WordPress供求插件文档&#xff0c;详情请查看 WordPress供求插件&#xff1a;一款专注于同城生活信息发布的插件-CSDN博客文章浏览阅读67次。WordPress供求插件&#xff1a;sliver-urban-life 是一款专注于提供同城生活信息发布与查看的插件&#xff0c;该插件可以实…

windows下编译boost1.84.0库

boost系列文章目录 文章目录 boost系列文章目录前言一、boost编译二、boost使用三 、参考 前言 Boost简介 官方网址 Boost提供免费的同行评审的可移植C源代码库。 我们强调与C标准库配合良好的库。Boost库旨在广泛使用&#xff0c;并可在广泛的应用程序中使用。Boost许可证鼓…

SpringBoot+Maven多环境配置模式

我这里有两个配置文件 然后在最外层的父级POM文件里面把这个两个配置文件写上 <profiles><profile><id>druid</id><properties><spring.profiles.active>druid</spring.profiles.active></properties><activation><…

sensor_msgs::LaserScan雷达数据转换成pcl::PointXYZ数据类型

文章目录 创建工作空间、功能包功能包文件 package.xml头文件、源码文件laserscan_to_pointcloud.hlaserscan_to_pointcloud.cc 代码解读编译文件 CMakeLists.txt运行效果 截图 创建工作空间、功能包 catkin_create_pkg laserscan_to_pointcloud sensor_msgs roscpp pcl_conve…

分享关于如何解决系统设计问题的逐步框架

公司广泛采用系统设计面试&#xff0c;因为在这些面试中测试的沟通和解决问题的技能与软件工程师日常工作所需的技能相似。面试官的评估基于她如何分析一个模糊的问题以及如何逐步解决问题。测试的能力还包括她如何解释这个想法&#xff0c;与他人讨论&#xff0c;以及评估和优…

回溯算法07-子集(Java/子集问题)

.子集 题目描述 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[…

ChatGPT高效提问——说明提示技巧

ChatGPT高效提问——说明提示技巧 现在&#xff0c;让我们开始体验“说明提示技巧”&#xff08;IPT, Instructions Prompt Technique&#xff09;和如何用它生成来自ChatGPT的高质量的文本。说明提示技巧是一个通过向ChatGPT提供需要依据的具体的模型的说明来指导ChatGPT输出…