C++_虚函数表

虚函数表

  • 介绍
  • 源码
  • 运行结果
    • 笔记扩充
    • 函数名联编
    • 静态联编
    • 动态联编

介绍

1.编译器通过指针或引用调用虚函数,不会立即生成函数调用指令,而是用 二级函数指针 代替

1.1确定真实类型
1.2找到虚函数表从而找到入口地址
1.3根据入口地址调用函数(PS:俗称 函数指针)

** 虚函数表 内部存储格式展示**
在这里插入图片描述
代码图详解
在这里插入图片描述

源码

#include<iostream>
#include<string>
using namespace std;class N
{
public:void foo(){cout << "N::foo" << endl;}void ber(){cout << "N::ber" << endl;}int m_a;int m_b;
};
class A
{
public:virtual void foo(){cout << "A::foo" << endl;}virtual void ber(){cout << "A::ber" << endl;}double m_a;int m_b;
};
class B:public A
{
public:void foo(){cout << "B::foo" << endl;}void ber(){cout << "B::ber" << endl;}
};
void main()
{A a;//在A类型中会多生成一个最大类型的 字节指针(内部存储的是函数指针)B b;//在B类型中会多生成一个最大类型的 字节指针(内部存储的是函数指针)A*pa = &b;//获取 N 类型大小cout << "sizeof(N):" << sizeof(N);//获取 N 相对于 m_a 的距离cout << ",m_a:" << offsetof(N, m_a);//获取 N 相对于 m_b 的距离cout << ",m_b:" << offsetof(N, m_b) << endl;//获取 A 类型大小cout << "sizeof(N):" << sizeof(A);//获取 A 相对于 m_a 的距离cout << ",m_a:" << offsetof(A, m_a);//获取 A 相对于 m_b 的距离cout << ",m_b:" << offsetof(A, m_b) << endl;cout << "-------------------分隔符-------------------" << endl;
//函数指针调用函数void *vf_ptr = *(void**)&a; //获取 A类型 中 a 地址cout <<"A类型 中 a 地址为:"<< vf_ptr << endl;    //打印 A类型 中 a 地址cout << "-------------------分隔符-------------------" << endl;//取别名typedef void(*VFUN)(void*); //VFUN 相当于 void(*)  // *VFUN 函数指针类型typedef VFUN* VPTR;         //VPTR 相当于 void(**) //指向函数指针类型的指针 VPTR虚函数表类型VPTR _vfptr = *(VPTR*)&a;   //获取 A类型 中 a 地址cout << "A类型 中 a 地址为:" << _vfptr << endl;   //打印 A类型 中 a 地址a.foo();                    //正常调用方法_vfptr[0](&a);              //编译器中调用方法 结果为:A::foo_vfptr[1](&a);              //编译器中调用方法 结果为:A::bercout << "-------------------分隔符-------------------" << endl;VPTR _vfptr1 = *(VPTR*)&b;   //获取 B类型 中 b 地址cout << "B类型 中 b 地址为:" << _vfptr1 << endl;   //打印 B类型 中 b 地址b.foo();                    //正常调用方法_vfptr1[0](&b);              //编译器中调用方法 结果为:B::foo_vfptr1[1](&b);              //编译器中调用方法 结果为:B::bersystem("pause");
}

运行结果

sizeof(N):8,m_a:0,m_b:4
sizeof(N):24,m_a:8,m_b:16
-------------------分隔符-------------------
A类型 中 a 地址为:0015DC80
-------------------分隔符-------------------
A类型 中 a 地址为:0015DC80
A::foo
A::foo
A::ber
-------------------分隔符-------------------
B类型 中 b 地址为:0015DCA0
B::foo
B::foo
B::ber
请按任意键继续. . .

笔记扩充

void(VFUN)(void) 的代码解释,参考下列源码

#include<iostream>
#include<string>
using namespace std;//构造3个通用函数
void TEST1(void) { printf("test1\n"); }//函数定义  
void TEST2(void) { printf("test2\n"); }//函数定义  
void TEST3(void) { printf("test3\n"); }//函数定义  
//声明(取别名为:(*func)函数)是 void 类型
typedef void(*func)(void);void test(int i)
{func vTask[3] = { &TEST1, &TEST2, &TEST3 };//func 类型代替 void功能func fun = vTask[i];//将vTask函数赋值到fun中(*fun)();//调用(*fun) ()函数
}
void main()
{test(0);test(1);test(2);system("pause");
}

函数名联编

将源代码中的函数调用解释为执行特定的函数代码块被称为 函数名联编

静态联编

1.静态联编是指 联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的, 又称为:早期联编
2.静态联编对函数的选择是基于指向对象的指针或者引用的类型
3.优点是效率高,灵活性差
4.静态联编是根据 所定义的类 来调用 类中函数(PS:相当于直接调用当前类代码,不会做任何检查)

动态联编

1.动态联编 是指联编在程序运行时动态地进行,这种联编又称为晚期联编。或动态束定
2.动态联编对成员函数的选择是基于对象的类型
3.优点是灵活性强,效率低
4.实际上是在运行时虚函数(virtual)的实现。(PS:先进行检查后,根据当时的情况来确定调用哪个同名函数)
动态联编 调用步骤:

1.1确定真实类型
1.2找到虚函数表从而找到入口地址
1.3根据入口地址调用函数(PS:俗称 函数指针)

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

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

相关文章

RT-Thread入门笔记3-线程的创建

线程 RT-Thread 中&#xff0c;线程由三部分组成&#xff1a;线程代码&#xff08;入口函数&#xff09;、线程控制块、线程堆栈. 线程代码: 线程控制块 : 线程控制块是操作系统用于管理线程的一个数据结构&#xff0c; 它会存放线程的一些信息&#xff0c; 例如优先级、 线程…

使用Notepad++将多行数据合并成一行

步骤 1、按CtrlF&#xff0c;弹出“替换”的窗口&#xff1b; 2、选择“替换”菜单&#xff1b; 3、“查找目标”内容输入为&#xff1a;\r\n&#xff1b; 4、“替换为”内容为空&#xff1b; 5、“查找模式”选择为正则表达式&#xff1b; 6、设置好之后&#xff0c;点击“全…

Vue3 父事件覆盖子事件,Vue2 的 v-on=“$listeners“ 的替代方案

在 Vue3 中&#xff0c;$listeners 被删除 子组件代码&#xff0c;需要特别注意的是事件名为 on 开头&#xff0c;例如 onBack。不确定的可以通过给父组件传递 事件或属性&#xff0c;再打印子组件的 attrs useAttrs()&#xff0c;来确定传值 // template v-bind"newA…

了解PyTorch中的缩放点积注意力及演示

torch.nn.functional.scaled_dot_product_attention 函数在 PyTorch 框架中用于实现缩放点积注意力&#xff08;Scaled Dot-Product Attention&#xff09;。这是一种在自然语言处理和计算机视觉等领域常用的注意力机制。它的主要目的是通过计算查询&#xff08;query&#xff…

Windows常用命令(文件相关、进程相关、网络相关、用户相关、特殊符号)

Windows常用命令 Windows常用命令 Windows常用命令0x01 基础操作0x02 文件操作0x03 进程操作0x04 网络相关0x05 用户相关0x06 特殊符号 0x01 基础操作 清屏&#xff1a;cls 关机&#xff1a;shutdown -s&#xff08;关机&#xff09;-r&#xff08;重启&#xff09; -f(强制)…

【Android 10 适配】隐私权限变更

更详细内容请参考 Android 10 中的隐私权变更 Android 10&#xff08;API 级别 29&#xff09;引入了多项功能和行为变更&#xff0c;旨在更好地保护用户的隐私。这些变更让用户更清楚地了解并更好地控制自己的数据及为应用提供的权能。 下面是 Android 10 中与隐私权限相关的…

Linux ----冯诺依曼体系结构与操作系统

目录 前言 一、冯诺依曼体系结构 二、为什么选择冯诺依曼体系结构&#xff1f; 三、使用冯诺依曼结构解释问题 问题1&#xff1a; 问题2: 四、操作系统 1.操作系统是什么 2.为什么需要操作系统 3.操作系统怎样管理的 4.如何给用户提供良好环境 五、我们是怎样调用系…

Windows Copilot 更新及使用教程

要更新并使用 Windows Copilot&#xff0c;在 Windows 11 上&#xff0c;首先确保您的系统已经更新到最新版本。Windows Copilot 是随 Windows 11 23H2 更新一起发布的新 AI 助手功能。它可以回答您的问题&#xff0c;完成任务&#xff0c;导航 Windows&#xff0c;并提高您的工…

native2ascii命令详解

native2ascii命令详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一同深入研究Java开发中常用的工具——"native2ascii"命令&a…

Github 2024-01-12Java开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-12统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Java项目10Vue项目3 Apache Flink: 开源流处理框架 创建周期&#xff1a;3506 天开发语言&#xff1a;Java协…

安卓 onActivityResult 废弃,registerForActivityResult 使用详解

文章目录 onActivityResult 存在的问题registerForActivityResult 有哪些改进registerForActivityResult 实战registerForActivityResult 自定义使用registerForActivityResult 开箱即用StartActivityForResultGetContent 后记注意事项附录 安卓的兼容性是出了名的低&#xff0…

C语言中的位运算详解

在C语言中&#xff0c;位运算符用于对二进制位进行操作&#xff0c;包括左移、右移、按位与、按位或、按位异或和按位取反等操作。本文将详细介绍C语言中的位运算符&#xff0c;包括运算规则和具体的例子。 1. 位运算符概述 C语言提供了一些位运算符&#xff0c;用于直接操作…

iOS rootless无根越狱解决方案

据游戏工委数据统计&#xff0c;2023年国内游戏市场实际销售收入与用户规模双双创下新高&#xff0c;游戏普遍采用多端并发方式&#xff0c;成为收入增长的主因之一。 中国市场实际销售收入及增长率丨数据来源&#xff1a;游戏工委 多端互通既是机遇&#xff0c;也是挑战。从游…

python实例100第16例:使用datetime输出指定格式的日期

题目&#xff1a;输出指定格式的日期。 程序分析&#xff1a;使用 datetime 模块。 #!/usr/bin/python # -*- coding: UTF-8 -*-import datetimeif __name__ __main__:# 输出今日日期&#xff0c;格式为 dd/mm/yyyy。更多选项可以查看 strftime() 方法print(datetime.date.t…

【AI大模型应用开发】1.0 Prompt Engineering(提示词工程)- 典型构成、原则与技巧,代码中加入Prompt

从这篇文章开始&#xff0c;我们就正式开始学习AI大模型应用开发的相关知识了。首先是提示词工程&#xff08;Prompt Engineering&#xff09;。 文章目录 0. 什么是提示词&#xff08;Prompt&#xff09;1. 为什么Prompt会起作用 - 大模型工作原理2. Prompt的典型构成、原则与…

【5】商密测评密码辅助工具

0X01 前言 最近在学了下商密测评&#xff0c;研究了下技术层面的测评&#xff0c;感觉找工具不方便&#xff0c;就顺手自己造了个辅助工具&#xff0c;都是自己遇到需要用的。 0x02 工具功能介绍 不爱打字&#xff0c;直接上图。后续根据技术测评层面需要继续完善和增加功能。…

基于VSG控制的MMC并网逆变器MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 根据传统同步发电机的运行特性设计了MMC-VSG功频控制器和励磁控制器&#xff0c; 实现了MMC-VSG逆变器对高压电网电压和频率的支撑。该模型包含MMC变流器模块&#xff0c;环流抑制模块&#xff0c;…

HackTheBox-Keeper

OpenVPN连接 连接上HackTheBox&#xff01; 同时找到这个靶机&#xff0c;进行join&#xff01;分配的靶机的地址位10.10.11.227&#xff01; 信息收集 nmap -sT --min-rate 10000 -p- 10.10.11.227 开放端口为22和80端口 服务版本和操作系统信息探测&#xff1a; nmap -s…

Milvus Cloud与携程的向量探索大公开

【User Tech】2024 我们来啦&#xff01; 今年&#xff0c;【User Tech】将更加专注于为社区用户提供技术功能解读、热点答疑&#xff0c;聚焦更丰富、更多样化的行业或使用场景的用户案例。我们期待通过分享更多关于 Milvus Cloud 的实战经验&#xff0c;为大家在 AI、大模型、…

ASM磁盘组配置共享存储:裸设备(60)_块设备(12)_(99)方式

--1.块设备方式配置共享存储 存储信息&#xff1a; 20个1TB的LUN&#xff0c;/dev/mapper/mpath1--mpath20 修改/etc/udev/rules.d/12-dm-permissions.rules添加内容 vi /etc/udev/rules.d/12-dm-permissions.rules ENV{DM_NAME}"mpath1", OWNER:"grid",…