多态、虚函数表与动态绑定的深入解析

目录

多态简介

虚函数表与动态绑定

虚函数表

动态绑定机制

内存与性能影响

纯虚函数与抽象类

纯虚函数

抽象类

动态类型转换与typeid操作符

dynamic_cast

typeid操作符

虚析构函数的重要性

在面向对象编程中,多态性是一种核心特性,它允许我们以统一的接口处理不同类型的对象,从而提高代码的灵活性和可扩展性。本文将深入探讨多态的概念,包括虚函数表、动态绑定的机制,以及它们对内存和性能的影响,并通过具体示例加以说明。

多态简介

多态性允许子类重写基类中的方法,使得通过基类引用来调用这些方法时,实际执行的是子类中对应的实现。这一特性在C++中主要通过虚函数来实现。

class Animal {
public:virtual void speak() { cout << "Some animal sound" << endl; }
};class Dog : public Animal {
public:void speak() override { cout << "Woof!" << endl; }
};int main() {Animal* pet = new Dog();pet->speak(); // 输出 "Woof!"delete pet;
}

在这个例子中,Animal 类定义了一个虚函数 speak()Dog 类继承自 Animal 并重写了 speak() 方法。通过基类指针 pet 调用 speak(),由于多态的存在,输出的是 "Woof!",而非 "Some animal sound"。 

虚函数表与动态绑定

虚函数表

每个包含虚函数的类都会有一个虚函数表(vtable),它是一个存储虚函数指针的数组。当创建此类的对象时,对象会有一个隐藏的指针(vptr)指向这个表。子类的虚函数表会继承并可能覆盖基类的虚函数。

动态绑定机制

动态绑定(也称作迟后联编)是在运行时确定调用哪个函数版本的过程。对于虚函数调用,编译器生成的代码会在运行时检查对象的实际类型,然后调用相应的函数版本。

内存与性能影响

  • 内存开销:虚函数表及其指针增加了每个对象的内存占用。
  • 执行时间:虚函数调用相较于非虚函数调用有额外的查找过程,可能导致性能下降。
  • 内联优化:编译器难以对虚函数进行内联优化,可能影响执行效率。

 

纯虚函数与抽象类

纯虚函数

class Shape {
public:virtual float area() const = 0; // 纯虚函数
};

纯虚函数没有具体实现,要求派生类必须给出定义

抽象类

含有纯虚函数的类被称为抽象类,不能实例化,但可以作为其他类的基类。

动态类型转换与typeid操作符

dynamic_cast

Animal* pet = new Cat();
Cat* cat = dynamic_cast<Cat*>(pet);
if (cat) {cout << "Pet is a cat." << endl;
} else {cout << "Pet is not a cat." << endl;
}

 dynamic_cast 可以安全地尝试将基类指针转换为派生类指针,如果转换不合法,则返回 nullptr(指针)或抛出异常(引用)。

typeid操作符

cout << typeid(*pet).name() << endl; // 输出类型信息

typeid 用于获取对象的实际类型信息,对于多态对象,它可以反映出动态类型。

虚析构函数的重要性

 

class Base {
public:virtual ~Base() { /* 清理基类资源 */ }
};class Derived : public Base {// 忽略虚析构函数~Derived() { /* 清理派生类资源 */ }
};int main() {Base* basePtr = new Derived();delete basePtr; // 派生类资源未被正确释放
}

若基类的析构函数不是虚函数,通过基类指针删除派生类对象时,只会调用基类的析构函数,导致派生类特有的资源未被释放。因此,基类的析构函数通常应声明为虚函数,确保所有资源被正确清理。

 本文通过对多态、虚函数表、动态绑定的机制及其影响的介绍,结合具体示例,深入浅出地解析了这些概念,希望对理解C++中的多态性有所帮助。

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

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

相关文章

单机多卡分布式训练策略——MirroredStrategy

前言 分布式训练是一种用于在多个设备或机器上同时训练深度学习模型的技术&#xff0c;它有助于减少训练时间&#xff0c;允许使用更多数据更快训练大模型。分布式训练重点关注数据并行性&#xff0c;本次试验使用的是单机多卡的分布式训练策略&#xff0c;也就是 MirroredStr…

mvn install -DskipTests

mvn install -DskipTests mvn install -DskipTests 不用做测试的打包代码

Task vs Thread

C#中的Task和Thread都是用于实现多线程和并发操作的重要组件&#xff0c;但它们在设计哲学、使用场景和功能特性上存在显著差异&#xff0c;同时也有一些内在的联系。 Task vs Thread 设计理念: Thread: 是操作系统级别的资源&#xff0c;代表了独立的执行路径。它是较为底层…

算法题目学习汇总

1、二叉树前中后序遍历:https://blog.csdn.net/cm15835106905/article/details/124699173 2、输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点&#xff0c;只能调整树中结点指针的指向。 public class Solution {private Tr…

多模态AI的挑战与早期壁垒的构建

伴随着Sora、GPT40的推出&#xff0c;多模态AI逐渐成为研究的热点和应用的趋势。然而&#xff0c;多模态AI的发展并非一帆风顺&#xff0c;它面临着诸多挑战和壁垒。 一、多模态AI的难点 多模态AI的核心在于将不同模态的信息&#xff08;如文本、图像、音频、视频等&#xff…

离线翻译器下载哪个好?这几个翻译器用过的人都说好

面对跨文化交流的挑战&#xff0c;如国际旅行或多元工作环境&#xff0c;语言障碍尤为突出。 特别是在信号弱或无网络覆盖的地区&#xff0c;翻译需求变得更加迫切。此时&#xff0c;一款优质的离线翻译app显得尤为重要。它能够在没有网络支持的情况下提供即时翻译服务&#x…

事实与价值很难对齐的原因

事实与价值的对齐是一个复杂的问题&#xff0c;因为事实通常是客观的、可观察的和基于证据的&#xff0c;而价值则是主观的、个人的和基于信仰或偏好的。事实与价值很难对齐的原因有以下几点&#xff1a; 1、事实的客观性和价值的主观性 事实是客观存在的&#xff0c;而价值则是…

空间数字孪生及应用

空间数字孪生&#xff08;SDT&#xff09;本质上是现实世界地理空间对象&#xff08;例如&#xff0c;建筑物、道路&#xff09;和系统&#xff08;例如&#xff0c;环境或交通监控&#xff09;的镜像表示。地理空间协会正式定义SDT为具有精确位置和维度属性的虚拟表示&#xf…

CF297C Splitting the Uniqueness 题解

CF297C Splitting the Uniqueness 题解 非常好构造题&#xff0c;使我的草稿纸旋转。 解法 我们记输入的数组为 a a a&#xff0c;需要输出的两个数组为 b , c b,c b,c&#xff08;因为当时起变量名起的&#xff09;。 考虑利用 a i a_i ai​ 互不相同的性质。 先将 a…

二叉树顺序结构——堆的结构与实现

二叉树顺序结构——堆的结构与实现 一、二叉树的顺序结构二、堆的概念及结构三、堆的实现堆向下调整算法堆的创建建堆时间复杂度堆的插入(堆向上调整算法)堆的删除堆的代码实现(使用VS2022的C语言)初始化、销毁构建、插入、删除返回堆顶元素、判空、返回有效元素个数 四、完整 …

20240610 基于QGIS生成地区示意图的地图shp文件

目录 本文目标前置条件具体步骤1. 创建Project2. 插入世界地图3. 对地区示意图进行地理匹配4. 创建shp文件&#xff0c;勾画轨迹 注意事项 本文目标 基于QGIS生成地区示意图的地图shp文件&#xff0c;此shp文件可以用来学习&#xff0c;但是未经审批不可用于发表。 前置条件 …

Python基础教程(十一):数据结构汇总梳理

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

10.3 Go 同步与通信

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Android Studio Jellyfish版本修改project使用特定jdk版本的步骤

android studio总是把这些东西改来改去让人十分恼火&#xff0c;IDE本身改来改去就让人无法上手就立即工作&#xff0c;很多时间浪费在IDE和gradle的配置和奇奇怪怪现象的斗智斗勇上&#xff0c;搞Android是真的有点浪费生命。一入此坑深不见底 jellyfish版安卓studio已经无法通…

算法 | 剪枝函数以及几种形式回溯法和分支限界法的区别算法特性分支限界法的思想分支限界法的基本步骤Prim和Kruscal回溯法的效率

what is 剪枝函数&#xff1f; 是对该问题能否得到最优解或者可行解的约束 限界函数&#xff1a;最优解 约束函数&#xff1a;可行解 回溯法和分支限界法的区别&#xff1a; 异&#xff1a; 回溯法分支限界法一次生成/扩展一个结点一次生成所有的孩子结点BFSDFS/最小耗费优…

Docker高级篇之轻量化可视化工具Portainer

文章目录 1. 简介2. Portainer安装 1. 简介 Portianer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便管理Docker环境&#xff0c;包括单机环境和集成环境。 2. Portainer安装 官网&#xff1a;https://www.portainer.io 这里我们使用docker命令安装&…

深入探讨API接口:定义、作用、设计原则及常见问题

API&#xff08;Application Programming Interface&#xff09;即应用程序编程接口&#xff0c;是软件系统间相互通信的桥梁&#xff0c;提供了一系列的约定和工具&#xff0c;使不同软件系统之间能够实现数据交换和功能调用。在软件开发中&#xff0c;API接口扮演着至关重要的…

渗透测试之内核安全系列课程:Rootkit技术初探(一)

今天&#xff0c;我们来讲一下内核安全&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 目前&#xff0c;在渗透测试领域&#xff0c;主要分为了两个发展方向&#xff0c;分别为Web攻防领域和PWN&#xff08;二进制安全&#xff09;攻防领域。在…

状态管理Vuex

官网&#xff1a;Vuex 是什么&#xff1f; | Vuex (vuejs.org)https://v3.vuex.vuejs.org/zh/ 创建一个vue2的新项目名为vuex-demo&#xff0c;安装命令 npm install vuex3 新建index.js import Vue from vue import Vuex from vuexVue.use(Vuex)const store new Vuex.Store(…

私域怎么引流?

在数字化营销日益重要的今天&#xff0c;私域流量成为了企业竞争的新焦点。私域流量指的是企业在自己的平台上所拥有和控制的用户资源&#xff0c;如企业官网、社交媒体账号、APP等。如何有效地进行私域引流&#xff0c;即将潜在用户引导至企业的私域平台&#xff0c;成为企业营…