指向成员函数的指针

2023-05-16

指向成员函数的指针

取一个非静态成员函数的地址,如果该函数是nonvirtual,则得到的结果是它在内存中真正的地址。然而这个值也不是完全的,它也需要被绑定于某个class object的地址上,才能够通过它调用该函数。所有的非静态成员函数都需要对象的地址(以参数this指出)。

一个指向成员函数的指针,其声明语法如下所示:

double      //return type

(Point::*  //class the function is member

pmf)        // name of pointer to member

();         // argument list

然后我们可以这样定义并初始化该指针:

double (Point::*coord)() = &Point::x;

也可以这样指定其值:

coord = &Point::y;

想调用它,可以这样做:

(origin.*coord)();或 (ptr->*coord)();

指向member function的指针的声明语法,以及指向“member selection运算符”的指针,其作用是作为this指针的空间保留者。这也就是为什么static member functions(没有this指针)的类型为“函数指针”,而不是“指向member function之指针”的原因。使用一个成员函数的指针,如果并不用于虚函数、多重继承、虚基类等情况的话,并不会比使用一个“nonmember function 指针”的成本更高。

 

支持“指向virtual member functions”的指针

注意下面的程序片段:

float (Point::*pmf)() = &Point::z;

Point *ptr = new Point3d;

pmf,一个指向成员函数的指针,被设置为Point::z()(一个虚函数)的地址。如果我们直接经由ptr调用z():

ptr->z();

则被调用的是Point3d::z()。但如果我们从pmf间接调用z()呢?

(ptr->*pmf)();

仍然是Point::z()被调用吗?也就是说,虚拟机制仍然能够在使用“指向成员函数的指针”的情况下正常运行吗?如何实现的呢?

面对一个虚函数,其地址在编译时期是未知的,所能知道的仅仅是虚函数在其相关的虚表中的索引值。也就是说,对一个虚成员函数取其地址,所能获得的只是一个索引值。假设我们有以下的Point声明:

Class Point{

public:

virtual ~Point();

float x();

float y();

virtual float z();

//…

}

然后取destructor的地址:

&Point::~Point;

得到的结果是1。取x()或y()的地址:

&Point::x();

&Point::y();

得到的是函数在内存中的地址,因为它们不是virtual。取z()的地址:

&Point::z();

得到的结果是2,通过pmf来调用z(),会被内部转化为一个编译时期的式子,一般形式如下:

( *ptr->vptr[(int)pmf] )( ptr );

 

对一个指向成员函数的指针评估求值,会因为该值有两种意义而复杂化,其调用操作也将有别于常规调用操作。pmf的内部定义,也就是:

float (Point::*pmf)();

必须允许该函数能够寻址出nonvirtual x()和virtual z()两个成员函数,这两个成员函数有着相同的原型,只不过其中一个代表内存地址,另外一个代表在对应虚表中的索引值。因此,编译器必须定义pmf使它能够(1)含有两种数值,(2)更重要的是其数值可以被区别代表内存地址还是虚表中的索引值。

在cfront2.0的非正式版本中,这两个值被内含在一个普通的指针内。它使用如下技巧:

(((int)pmf) & ~127)

? (*pmf)(ptr)                            //non-virtual invocation

: ( *ptr->vptr[(int)pmf] )( ptr );   //virtual invocation

这种实现技巧必须假设继承体系中最多只能够有128个虚函数。这并不是我们所希望的,但却证明是可行的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

指向成员函数的指针 的相关文章

  • dfs和bfs能解决的问题

    一 理解暴力穷举之dfs和bfs 暴力穷举 暴力穷举是在解决问题中最常用的手段 xff0c 而dfs和bfs算法则是这个手段的两个非常重要的工具 其实 xff0c 最简单的穷举法是直接遍历 xff0c 如数列求和 xff0c 遍历一个数组即
  • C语言中给指定的内存地址赋值(通过指针)

    应用中的实际问题 xff1a 通过I2C接口发送到MCU一个地址数据 xff08 unsigned char AdData xff0c 一个待写入数据 xff08 unsigned char DaData 希望将DaData的值写到MCU内
  • ubuntu 14.04+indigo环境下dashgo d1+lms100运行环境搭建建图

    1 设置用户的串口读取权限 sudo usermod a G dialout your user name your user name替换为实际用户名 2 安装ROS依赖包 sudo sh c 39 echo 34 deb http pa
  • L298N双路驱动直流电机方案(支持PWM+正反转)

    目录 写在前面 xff08 吐槽吐槽 xff09 正文 最后 写在前面 xff08 吐槽吐槽 xff09 我想要驱动两个直流电机 直流电机 xff0c 说白了 xff0c 就是那种小马达 xff0c 小时候玩四驱车时那种没有正负极的马达 x
  • 基于业务测试的增量代码覆盖率实现

    前言 xff1a 本文主要实现的功能是代码增量覆盖率 xff0c 且基于覆盖率已实现 xff0c 可拿到全量覆盖率结果的情况下 xff0c 给出的增量代码覆盖率方法实现 xff0c 虽然各类语言有差别 xff0c 但是实现的基本思路都是一致
  • 测试工程师进阶测试开发工程师

    黑盒测试 xff1a 没有开发基础的测试工程师通常由黑盒测试做起 xff0c 不过根据个人经验 xff0c 这部分工作依然会给我们带来很多经验性的东西 xff0c 比如熟悉浏览器特性 xff0c 熟悉公司业务流程 xff0c 业务知识 xf
  • 轻量级接口自动化测试工具

    相信所有公司在起步自动化的时候做的都是接口自动化 xff0c 为什么呢 xff1f 理由很简单 xff0c 接口自动化复用性强 xff0c 易维护 xff0c 他的产出效率要远远高于UI自动化 xff0c 想想如果你的公司有成百上千的接口
  • JAVA实现HTTPS协议POST请求JSON报文

    HTTPS和HTTP的区别 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息 HTTP协议以明文方式发送内容 xff0c 不提供任何方式的数据加密 xff0c 如果攻击者截取了Web浏览器和网站服务器之间的传输报文 x
  • Jmeter之JAVA Request的应用

    当我们使用Jmeter进行接口测试的时候 xff0c 我们一定会遇到一个问题 xff0c 那就是如果这些接口不是http协议的 xff0c 是经过封装以后的接口 xff0c 用Jmeter该怎么解决呢 xff1f 当你想到这个问题 xff0
  • FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用

    FreeRTOS例程3 串口中断接收不定长的数据与二值信号量的使用 知乎 zhihu com
  • 使用airtest实现UI自动化之环境搭建

    1 xff0c 安装python python版本为3 7 1 2 xff0c 安装airtest xff0c pocoui模块 在安装时碰到的问题 xff1a 1 xff09 使用pip命令报错 xff0c 报SSL证书无法识别错误 解决
  • HTTP Digest Authentication在实际应用中的问题

    作者 xff1a 老王 Basic认证实际上是明文传递密码 xff0c 所以 RFC2617里定义了Digest认证以取代它 xff0c 其计算方法如下 xff1a 其中HA1计算方法为 xff1a 如果qop选项的值为auth xff0c
  • 1天精通Apipost--全网最全gRPC调试和智能Mock讲解!

    gRPC 接口调试 grpc 作为一个老程序员 xff0c 最近公司技术架构用到了gPRC xff0c 但国内很少有支持这个的工具 xff0c 大部分都只是支持http 由于我同时也是Apipost骨灰级用户 xff0c 于是就在他们官网的
  • CAN总线波特率的设定——以STM32为例

    波特率的设定 首先是几个名词的含义 xff0c CAN里面1个位的构成如下 注意采样点的位置在PBS1和PBS2的中间 根据这个位时序就可以计算波特率了 最小时间单位 xff08 Tq xff0c Time Quantum xff09 同步
  • 2021电赛备赛心路历程(含代码例程)

    作为一个电子学院学生 xff0c 大二暑假才开始自学单片机知识 xff08 还是因为报名了电赛而不得不去学 xff09 xff0c 深感愧疚 从今年7月至8 4的将近四周时间内哩哩啦啦学了一些基础模块 xff08 其中光是练习点灯和其他基础
  • 20201114-三轴云台storm32 BGC HAKRC调试+

    storm32 BGC HAKRC 2轴云台支持俯仰 xff08 抬头低头 xff09 以及横滚 xff1b 三轴多了一个航向 支持锁头模式 xff0c 拍摄更方便 可以控制俯仰通过接收机或者其他单独PWM通道 可以设置跟随模式或者锁定模式
  • KEIL5中头文件路劲包含问题

    方式1 xff1a 1 Keil中添加头文件相对路劲的方法 在c c 43 43 配置中添加路劲 xff0c 最终是将添加的绝对路径转化为相对路径 xff1b 注意 xff1a 相对路径的当前位置指 uvproj文件所在位置 在C C 43
  • php curl函数应用方法之模拟浏览器

    curl 是使用URL语法的传送文件工具 xff0c 支持FTP FTPS HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE和LDAP curl 支持SSL证书 HTTP POST HTTP PUT FTP
  • WireShark基本抓包数据分析

    WireShark抓包数据分析 xff1a 1 TCP报文格式 源端口 目的端口 xff1a 16位长 标识出远端和本地的端口号 顺序号 xff1a 32位长 表明了发送的数据报的顺序 确认号 xff1a 32位长 希望收到的下一个数据报的

随机推荐

  • VScode下运行调试C++文件

    1 下载vscode 这个可以直接去官网下载 2 下载mingw64 下载mingw64就是下载C 43 43 的编译器g 43 43 和调试器gdb 这个也可以去官网下载 xff0c 下载安装完成后去配置环境变量 我将mingw64安装在
  • c++模板的优点和缺点

    作为C 43 43 语言的新组成部分 xff0c 模板引入了基于通用编程的概念 通用编程是一种无须考虑特定对象的描述和发展算法的方法 xff0c 因此它与具体数据结构无关 但在决定使用C 43 43 模板之前 xff0c 让我们分析一下使用
  • 基于导航网格的A星寻路(Navigation mesh)

    最近花了几个月的时间实现了导航网格寻路和导航网格自动生成 导航网格数据结构定义 由于数据之间有着层级关系 xff0c 所以采用XML进行定义 navmesh基本元素 xff1a 顶点 Verts 43 可走边 Edges 43 凸多边形 P
  • cmake 引入 动态库、静态库

    动态库 xff1a link directories PROJECT SOURCE DIR lib 添加动态连接库的路径 target link libraries project name lMNN 添加libMNN so 静态库 xff
  • 利用JSP内置对象Request和Application实现用户名密码登录注册进入首页显示

    学习目标 xff1a 实验名称 xff1a JSP内置对象目的 xff1a 掌握JSP页面的全部语法 能够编写基本的JSP网页 学习内容 xff1a 1 实验 地点 周三2单元 xff0c 10617综合一实验室 自带电脑 目的 掌握各种内
  • 【如何写CMake】一个解决方案,多个工程

    文章目录 代码参考 一个解决方案 xff0c 多个工程 xff0c 即多个exe dll lib等 代码 多加几个ADD EXECUTABLE即可 1 cmake verson xff0c 指定cmake版本 cmake minimum r
  • 指针、寄存器、位操作

    定义寄存器的绝对地址 xff0c 并转换为指针进行位操作 1 位操作示例一 define PERIPH BASE unsigned int 0x40000000 define APB2PERIPH BASE PERIPH BASE 43 0
  • 详解TCP连接的建立

    TCP首部格式 TCP报文段首部的前20个字节是固定的 xff0c 后面有4N字节是根据需要而增加的选项 xff0c 因此TCP报文段的最小长度为20字节 首部固定部分的各字段的意义如下 xff1a 1 源端口和目的端口 xff1a 加上I
  • printf打印函数的原理浅析

    printf的底层原理浅析 目录 printf的底层原理浅析前言函数变参格式解析一个简单的printf示例结语 补充 前言 最近在学习linux内核的时候用到了自定义实现的printf xff0c 学习了一下 xff0c 在此记录 xff0
  • 基于公开网站挖掘敏感信息的研究与分析- Fofa 搜索

    基于公开公开网站挖掘敏感信息的研究与分析 Fofa 搜索 一 引言 1 1项目概述 基于公开网站的敏感信息挖掘研究与分析 xff1a 针对目前网络安全整体的趋势我们从google等搜索引擎 Github等代码库 FOFA等空间搜索这三个方面
  • HTTP报文

    一 HTTP报文的结构 用于HTTP协议交互的信息 xff0c 称为HTTP报文 客户端的HTTP报文称为请求报文 xff0c 服务端的称为响应报文 HTTP报文结构如下图 xff1a 下面是请求报文的一个实例 xff1a 请求行 xff1
  • 用C++写一个UDP发送和接收程序

    发送程序Sender cpp include lt stdio h gt include lt string gt include lt iostream gt include lt winsock h gt using namespace
  • STM32自学笔记(五)串口通信

    xff08 想要深入理解就把前面的看下 xff0c 否则直接看使用总结即可 xff09 usart文件夹 usart 文件夹内包含了 usart c和usart h两个文件 这两个文件用于串口的初始化和中断接收 代码只针对了串口1 xff0
  • sockaddr_in详解

    struct sockaddr in short sin family Address family一般来说AF INET xff08 地址族 xff09 PF INET xff08 协议族 xff09 unsigned short sin
  • ubuntu下好用的TCP/UDP调试工具

    github官方链接 GitHub s kyo mNetAssist mNetAssist A UDP TCP Assistant 编译好的安装包 ubuntu下好用的TCP UDP调试工具 网络设备文档类资源 CSDN下载 1 解压dpk
  • Linux网络编程之connect函数分析

    在一个 CLIENT SERVER模型的网络应用中 xff0c 客户端的调用序列大致如下 xff1a socket gt connect gt recv send gt close 其中socket没有什么可疑问的 xff0c 主要是创建一
  • linux route 命令

    显示现在所有路由 route n root 64 Ubuntu route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10
  • 大量LAST_ACK 分析过程

    记录一下自己的思想过程 现象 在netstat的时候发现大量处于LAST ACK状态的TCP连接 xff0c 达到在ESTABLISHED状态的90 以上 root 64 ccsafe netstat ant fgrep 34 34 cut
  • const 与重载

    const到底是不是一个重载的参考对象 xff0c 请看下面的例子 class A public void f int i std cout lt lt 34 1 34 函数1 void f int i const std cout lt
  • 指向成员函数的指针

    指向成员函数的指针 取一个非静态成员函数的地址 xff0c 如果该函数是nonvirtual xff0c 则得到的结果是它在内存中真正的地址 然而这个值也不是完全的 xff0c 它也需要被绑定于某个class object的地址上 xff0