如何使用指向类的成员函数的指针(详解!)

恼人的函数指针(二):指向类成员的指针 个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 前面曾写过一篇恼人的函数指针(一),总结了普通函数指针的声明、定义以及调用,还有函数指针数组,函数指针用作返回值等。但是作为C++的研读,我发现我漏掉了一个最重要的内容,就是指向类成员的指针,这里将做相应补充(相关代码测试环境为vs 2010)。 指向类成员的指针总的来讲可以分为两大类四小类(指向数据成员还是成员函数,指... 阅读详情

微笑吐舌头我们首先复习一下"指向函数的指针"如何使用?

  1. void print()  
  2. {  
  3. }  
  4. void (*pfun)(); //声明一个指向函数的指针,函数的参数是 void,函数的返回值是 void  
  5. pfun = print;   //赋值一个指向函数的指针  
  6. (*pfun)();    //使用一个指向函数的指针  

微笑吐舌头比较简单,不是吗?为什么*pfun需要用()扩起来呢?

微笑吐舌头因为*的运算符优先级比()低,如果不用()就成了*(pfun()).

微笑吐舌头指向类的成员函数的指针不过多了一个类的限定而已!

  1. class A  
  2. {  
  3. void speak(char *, const char *);   
  4. };  
  5.   
  6. void main()  
  7. {  
  8. A a;  
  9. void (A::*pmf)(char *, const char *);//指针的声明  
  10. pmf = &A::speak; //指针的赋值  
  11. }  

微笑吐舌头一个指向类A 成员函数的指针声明为:

微笑吐舌头void (A::*pmf)(char *, const char *);

微笑吐舌头声明的解释是:pmf是一个指向A成员函数的指针,返回无类型值,函数带有二个参数,参数的类型分别是char *和const char *。除了在星号前增加A::,与声明外部函数指针的方法一样。一种更加高明的方法是使用类型定义:例如,下面的语句定义了PMA是一个指向类A成成员函数的指针,函数返回无类型值,函数参数类型为char *和const char *:

委屈快哭了typedef void(A::*PMA)(char *,const char *);

委屈快哭了PMA pmf= &A::strcat;//pmf是 PMF类型(类A成员指针)的变量

委屈快哭了下面请看关于指向类的成员函数的使用示例:

微笑吐舌头我们首先复习一下"指向函数的指针"如何使用?

  1. void print()  
  2. {  
  3. }  
  4. void (*pfun)(); //声明一个指向函数的指针,函数的参数是 void,函数的返回值是 void  
  5. pfun = print;   //赋值一个指向函数的指针  
  6. (*pfun)();    //使用一个指向函数的指针  

微笑吐舌头比较简单,不是吗?为什么*pfun需要用()扩起来呢?

微笑吐舌头因为*的运算符优先级比()低,如果不用()就成了*(pfun()).

微笑吐舌头指向类的成员函数的指针不过多了一个类的限定而已!

  1. class A  
  2. {  
  3. void speak(char *, const char *);   
  4. };  
  5.   
  6. void main()  
  7. {  
  8. A a;  
  9. void (A::*pmf)(char *, const char *);//指针的声明  
  10. pmf = &A::speak; //指针的赋值  
  11. }  

微笑吐舌头一个指向类A 成员函数的指针声明为:

微笑吐舌头void (A::*pmf)(char *, const char *);

微笑吐舌头声明的解释是:pmf是一个指向A成员函数的指针,返回无类型值,函数带有二个参数,参数的类型分别是char *和const char *。除了在星号前增加A::,与声明外部函数指针的方法一样。一种更加高明的方法是使用类型定义:例如,下面的语句定义了PMA是一个指向类A成成员函数的指针,函数返回无类型值,函数参数类型为char *和const char *:

委屈快哭了typedef void(A::*PMA)(char *,const char *);

委屈快哭了PMA pmf= &A::strcat;//pmf是 PMF类型(类A成员指针)的变量

委屈快哭了下面请看关于指向类的成员函数的使用示例:

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Person  
  5. {  
  6. public:  
  7.     /*这里稍稍注意一下,我将speak()函数设置为普通的成员函数,而hello()函数设置为虚函数*/  
  8.     int value;  
  9.     void speak()      
  10.     {  
  11.         cout << "I am a person!" << endl;  
  12.         printf ("%d\n", &Person::speak); /*在这里验证一下,输出一下地址就知道了!*/  
  13.     }  
  14.     virtual void hello()  
  15.     {  
  16.         cout << "Person say \"Hello\"" << endl;  
  17.     }  
  18.     Person()  
  19.     {  
  20.         value = 1;  
  21.     }  
  22.   
  23. };  
  24.   
  25.   
  26.   
  27. class Baizhantang: public Person  
  28. {  
  29. public:  
  30.     void speak()  
  31.     {  
  32.         cout << "I am 白展堂!" << endl;  
  33.     }  
  34.     virtual void hello()  
  35.     {  
  36.         cout << "白展堂 say \"hello!\"" << endl;  
  37.     }  
  38.     Baizhantang()  
  39.     {  
  40.         value = 2;  
  41.     }  
  42. };  
  43.   
  44. typedef void (Person::*p)();//定义指向Person类无参数无返回值的成员函数的指针  
  45. typedef void (Baizhantang::*q)();//定义指向Baizhantang类的无参数无返回值的指针  
  46.   
  47. int main()  
  48. {  
  49.     Person pe;  
  50.     int i = 1;  
  51.     p ip;  
  52.     ip = &Person::speak;    //ip指向Person类speak函数  
  53.     (pe.*ip)();     //这个是正确的写法!  
  54.   
  55.     //--------------------------------------------  
  56.     //  result : I am a Person!   
  57.     //           XXXXXXXXXX(表示一段地址)  
  58.     //--------------------------------------------  
  59.   
  60.     /* 
  61.     *下面是几种错误的写法,要注意! 
  62.     *       pe.*ip(); 
  63.     *       pe.(*ip)(); 
  64.     *       (pe.(*ip))(); 
  65.     */  
  66.   
  67.     Baizhantang bzt;  
  68.       
  69.     q iq = (void (Baizhantang::*)())ip; //强制转换  
  70.     (bzt.*iq)();  
  71.   
  72.     //--------------------------------------------  
  73.     //  result : I am a Person!  
  74.     //           XXXXXXXXXX(表示一段地址)  
  75.     //--------------------------------------------  
  76.   
  77.     /*  有人可能会问了:ip明明被强制转换成了Baizhantang类的成员函数的指针,为什么输出结果还是: 
  78.     * I am a Person!在C++里面,类的非虚函数都是采用静态绑定,也就是说类的非虚函数在编译前就已经 
  79.     *确定了函数地址!ip之前就是指向Person::speak函数的地址,强制转换之后,只是指针类型变了,里面 
  80.     *的值并没有改变,所以调用的还是Person.speak函数,细心的家伙会发现,输出的地址都是一致的. 
  81.     *这里要强调一下:对于类的非静态成员函数,c++编译器会给每个函数的参数添加上一个该类的指针this,这也 
  82.     *就是为什么我们在非静态类成员函数里面可以使用this指针的原因,当然,这个过程你看不见!而对于静态成员 
  83.     *函数,编译器不会添加这样一个this。 
  84.     */  
  85.       
  86.     iq = &Baizhantang::speak;   /*iq指向了Baizhantang类的speak函数*/  
  87.     ip = (void (Person::*)())iq;    /*ip接收强制转换之后的iq指针*/  
  88.     (bzt.*ip)();  
  89.   
  90.     //--------------------------------------------  
  91.     //  result : I am 白展堂!  
  92.     //--------------------------------------------  
  93.   
  94.     (bzt.*iq)();//这里我强调一下,使用了动态联编,也就是说函数在运行是才确定函数地址!  
  95.   
  96.     //--------------------------------------------  
  97.     //  result : I am 白展堂!  
  98.     //--------------------------------------------  
  99.   
  100.     /*这一部分就没有什么好讲的了,很明白了!由于speak函数是普通的成员函数,在编译时就知道 
  101.     *到了Baizhantang::speak的地址,因此(bzt.*ip)()会输出“I am 白展堂!”,即使iq被强制转换 
  102.     *成(void (Person::*)())类型的ip,但是其值亦未改变,(bzt.*iq)()依然调用iq指向处的函数 
  103.     *即Baizhantang::speak. 
  104.     */  
  105.   
  106.   
  107.     /*好了,上面讲完了普通成员函数,我们现在来玩一点好玩的,现在来聊虚函数*/  
  108.     ip = &Person::hello;    /*让ip指向Person::hello函数*/  
  109.     (pe.*ip)();  
  110.   
  111.     //--------------------------------------------  
  112.     //  result : Person say "Hello"  
  113.     //--------------------------------------------  
  114.   
  115.     (bzt.*ip)();  
  116.   
  117.     //--------------------------------------------  
  118.     //  result : 白展堂 say "Hello"  
  119.     //--------------------------------------------  
  120.   
  121.     /*咦,这就奇怪了,为何与上面的调用结果不类似?为什么两个调用结果不一致?伙伴们注意了: 
  122.     *speak函数是一个虚函数,前面说过虚函数并不是采用静态绑定的,而是采用动态绑定,所谓动态 
  123.     *绑定,就是函数地址得等到运行的时候才确定,对于有虚函数的类,编译器会给我们添加一个指针 
  124.     *vptr,指向一个虚函数表vptl,vptl里面存放着虚函数的地址,子类继承父类的时候,也会继承这样 
  125.     *一个指针,如果子类复写了虚函数,那么该表中该虚函数地址将会由父类的虚函数地址替换成子类虚 
  126.     *函数地址,编译器会把(pe.*ip)()转化成为(pe.vptr[1])(pe),加上动态绑定,结果会输出: 
  127.     *       Person say "Hello"    
  128.     *(bzt.*ip)()会被转换成(bzt.vptr[1])(pe),自然会输出: 
  129.     *       白展堂 say "Hello" 
  130.     *ps:这里我没法讲得更详细,因为解释起来肯定是很长很长的,感兴趣的话,我推荐两本书你去看一看: 
  131.     *   第一本是侯捷老师的<深入浅出MFC>,里面关于c++的虚函数特性讲的比较清楚; 
  132.     *   第二本是侯捷老师翻译的<深度探索C++对象模型>,一听名字就知道,讲这个就更详细了; 
  133.     *当然,不感兴趣的同学这段解释可以省略,对与使用没有影响! 
  134.     */  
  135.   
  136.     iq = (void (Baizhantang::*)())ip;  
  137.     (bzt.*iq)();  
  138.   
  139.     //--------------------------------------------  
  140.     //  result : 白展堂 say "Hello"  
  141.     //--------------------------------------------  
  142.       
  143.     system("pause");  
  144.     return 0;  
  145. } 

ESP32使用microPython控制240x240彩色屏幕显示中文 王铭东老师详细讲解了讲了关于240x240屏幕的一些基础东西,我这里在原功能的基础上拓展了中文显示的功能,顺带修改了实际操作过程中程序中遇到的一些问题。 阅读详情

相关推荐

四、SVN客户端tortoiseSVN的基本功能介绍

档案浏览器(Repo-browser) 鼠标右键–>tortoiseSVN->版本库浏览器 输入版本库URL地址,进入如菜单界面 版本库浏览器支持SVN及http两种最常用的通信协议 SVN服务器访问方式 方法 模式 访问方法 File:// 直接版本库访问(本地磁盘) http:// 通过配置subversion的WEB服务器的WEBDAV协议 http...

也许是我送你哦 1012

C++指向类成员的函数指针

定义:类成员函数指针(member function pointer),是 C++ 语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息。基本上要注意的有两点:1、函数指针赋值要使用 & 2、使用 .* (实例对象)或者 ->*(实例对象指针)调用类成员函数指针所指向的函数 下面看两个例子:对于 nonstatic member function (非静态成员函数)取地址,获得该函数在内存中的实际地址对于 virtual function(虚函数), 其地址在编译时期

weixin_43488671的博客 3892

别再手动改颜色了!用这个Word宏,一键搞定Zotero参考文献超链接的蓝色样式

本文介绍如何利用Word宏一键修改Zotero参考文献的超链接颜色,解决手动调整的繁琐问题。通过详细的VBA代码解析和高级定制方案,帮助科研人员快速实现文献引用的自动化格式优化,提升论文排版效率。特别适合需要批量处理APA等标准格式蓝色超链接的用户。

weixin_30875157的博客 515

C++中指向类的指针

1.指向类的指针 一个指向C++类的指针与指向结构体的指针类似,访问指向类的指针的成员,需要使用成员访问运算符->,就像访问指向结构体的指针一样。与所有的指针一样,必须在使用指针之前,对指针进行初始化。 实例如下: #include "iostream" using namespace std; class Box{ public: ...

CurryCoder的个人博客 4268

解决‘GLIBC_2.28 not found‘错误:手把手教你升级glibc到最新版(附中文乱码修复)

本文提供了一份详尽的Linux系统glibc升级实战指南,旨在解决常见的'GLIBC_2.28 not found'错误。文章不仅涵盖从风险评估、环境准备到编译安装的完整流程,还特别加入了精简本地化数据以修复中文乱码的实用技巧,帮助管理员和开发者在安全可控的前提下完成系统核心库的升级。

a1b2c3d的博客 1345

MacTeX+TeXstudio:Macbook配置本地Latex看这一篇就够了

这个博客记录本人在MacBook上配置本地Latex的流程,其中选择的编译环境为MacTeX,编辑器为TeXstudio。采用的原因主要两点:一个是本人配置的原因主要是用来撰写毕业论文,希望能够尽可能简化设置流程,专注内容表达;第二是由于本人还有一个windows系统的笔记本,想要编辑器在专注写作体验的同时在两个系统上能够都适配,从而减少切换效率,故选择此组合。这篇文章介绍并详细记录了本人的安装流程,有相同需求的同志也可借鉴。

Katherine-XY的博客 6984

C++成员函数指针的应用

        C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。   刚遇到这种语法时也许会让你止步不前。但你会发现,使用恰当的类型定义之后,复杂的语法是可以简化的。本文引导你了解成员函数指针的声明,赋值和调用回叫函数。   成员函数指针的声明

搜索如风 3702

[3.4]【机器人运动学MATLAB实战分析】PUMA560机器人逆运动学MATLAB计算

PUMA560是六自由度关节型机器人,其6个关节都是转动副,属于6R型操作臂。各连杆坐标系如图1,连杆参数如表1所示。本文对PUMA560机器人逆运动学进行分析并MATLAB计算

m0_72676510的博客 1947

C++指向对象成员函数的指针

指向对象成员函数的指针 对象的成员函数是一个函数,那么,我们可以定义一个函数指针,指向对象的成员函数。但是,该函数指针变量的定义,与普通的函数指针变量定义不同。 首先,我们先看看指向“普通函数”的指针变量的定义方法: 数据类型名 (* 指针变量名)(参数列表); 例如: void (*pf)(int); //定义函数指针pf,指向的函数是带有1个int类型的参数,并且,返回类型是void 所以,它可以指向一个函数,并通过函数指针调用该函数,如下: pf = func;...

LC的专栏 3507

4 屏 + 8 摄像头一开,谁在悄悄拖慢你的座舱域控?

如果你觉得座舱卡顿:❌ 别第一反应怪 SoC❌ 别盲目堆算力。

weixin_43199439的博客 148

直捣黄龙~

这篇文章描述了一个矩阵寻路问题,要求计算从起点到终点的最短路径数量及长度。主要思路是通过BFS算法解决:首先标记哨兵警戒区域为禁区,然后从起点出发进行广度优先搜索,记录每个位置的最短步数和路径条数。当到达终点时,输出路径数和步数;若不可达则返回(0,0)。算法使用队列实现BFS,同时处理路径统计和步数记录,适用于网格寻路类问题。

面试高手的博客 217

指向成员函数的指针和this指针

1.指向类的成员函数的指针 (1)定义的一般形式:数据类型 (类名:: * 指针变量名)(参数表列) (2)使成员函数指针指向类的共用成员函数的一般形式:函数指针名=&类名::函数名 (3)利用函数指针调用类的成员函数一般形式:(对象名 . 函数指针名)() #include using namespace std; class Time { public: Time(int h, in...

weixin_43597743的博客 2810

SAP CAP core data service 里 association 和 composition 的区别

我们进行 SAP CAP 开发时,在schema.cds里进行数据建模,可以使用 association 和 composition,来描述两个 entity 之间的关联关系。在 SAP BTP 的 Cloud Application Programming Model (CAP) 中,cds文件定义了数据模型,而和是用于建立实体关系的两种关键机制。理解它们的区别对于构建高效、清晰的 CAP 数据模型至关重要。下面,我们将通过严谨的逻辑推理,结合代码示例,深入分析和之间的核心差异。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 323

让我们看看C++类中的默认成员函数到底是什么?(外加常量指针和指向常量指针的区别)

默认成员函数:就是即使类内什么都不写(就像之前我们在类对象的大小那里说的空类),编译器也会自动生成6个默认的成员函数,这6个成员函数称为默认成员函数。

2302_77620024的博客 3965

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

大胆使用指向成员函数的指针

大胆使用指向成员函数的指针         指向成员函数的指针是C++中比较复杂的语法结构,然而,它却是事件驱动和多线程环境中不可缺少的,特别是当从外部调用成员函数的时候。在多线程里,每一个线程都通过指向成员函数的指针调用这一函数。如果C++没有这些语法特性,那么在很多情况下进行C++程序开发会遇到很多麻烦。        也许你开始会被这一性质的语法吓倒,但当你熟悉之后你就会觉得它相当方便,

Zaobird的专栏 4879

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

指向成员函数的指针

转自:http://www.cppblog.com/colys/articles/25785.html C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。   刚遇到这种语法时也许会让你止步不前。但你会发现,使用恰当的类型定义之后,复杂的

Dereky's Blog 3471

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

指向类的成员的指针

指向类的成员的指针    在C++中,可以说明指向类的数据成员和成员函数的指针。    指向数据成员的指针格式如下:    ::*    指向成员函数的指针格式如下:    (::*)()    例如,设有如下一个类A:    class A    {    public:        int fun (int b) { return a*c+b; }        A(int i) { a=i

qhmao的专栏 4298

C++ const 指针与指向const的指针

最近在复习C++,指针这块真的是重难点,很久了也没有去理会,今晚好好总结一下const指针,好久没有写过博客了,记录一下~ const指针的定义:   const指针是指针变量的值一经初始化,就不可以改变指向,初始化是必要的。其定义形式如下: type *const 指针名称;   声明指针时,可以在类型前或后使用关键字const,也可在两个位置都使用。例如,下面都是合法的

Hank铄 5610

类里面的成员函数指针使用

先看代码 #include using namespace std; typedef void (*func)(); //含简单的定义一个函数指针,很容易用这个方法来实现指令,用作各种handler等等 void print() { cout << "print" <<endl; } class A { typedef void (A::*clas

学习笔记 6084

函数指针,指向成员函数的指针与指向成员变量的指针

<br />1.从函数指针说起<br />   可以声明一个指向特定函数的指针:<br />       void (*fp)(int); //指向函数的指针(函数指针)<br />   注意:其中的括号是必不可少的,它表明fp是一个指向返回值为void的函数的指针,而不是返回值为void*的函数。<br />      void* fp(int);  //声明一个返回值为void*的函数(指针函数)<br />   <br />   函数指针的赋值:指向函数的指针可以为空,否则它就应该指向一个具有适当类型

wangsifu2009的专栏 952

类和对象——类的成员函数的this指针

c++的类中的this指针。

m0_73693552的博客 1415

类的普通成员函数的指针

很多朋友都知道虚函数有虚函数指针,并且存放在对象的虚函数表中,它和普通成员变量一样与对象相关,因此虚函数的指针是对象级的。一个类的普通成员函数是类级的,因此普通成员函数的指针也是类级的。一个类的普通成员函数的指针,少有文献提及,因为很少需要用到普通成员函数的指针。尽管如此,在一些特殊的场合,还是有可能需要用到的。 1) 成员函数简介 在C++中,成员函数的指针是个比较特殊的东西。对普通的函数

玄机逸士的专栏 3285

由类的成员函数深入指针

  先看这样一段代码 class test { public: test(int i){ m_i=i;} test(){}; void hello() { printf("hello/n"); } private: int m_i; }; int main() {  test *p=new test();  p->hello();  p=NULL;  p->hello(); }  

hairetz的专栏 6828

C++之指向对象成员函数的指针

1. 普通函数的指针变量定义    数据类型名 (*指针变量名)(参数列表);    例如:void (*p)( ); //p指向void型函数的指针变量;          p = fun;      //fun入口地址赋予p;          (*p)( );      //调用fun函数; 2. 指向对象成员函数的指针变量[指向对象成员函数的指针变量与普通函数的指针变量的根本区别

CXHPLY的专栏 3402
上一篇: fatal error C1859: 意外的预编译头错误
下一篇: C语言回调函数学习
Maybe______
博客等级 码龄10年 26粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值