C++ 成员函数指针的问题 pointer-to-member-function

本文探讨了C++中的成员函数指针,包括非静态成员函数和静态成员函数的区别,并通过实例解释了成员函数指针类型的特殊性。在C++中,成员函数指针的使用涉及特定的操作符->*,并强调了正确使用该操作符的重要性。文章还提到了在使用成员函数指针时遇到的编译错误及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在写cocos2d-x游戏的时候,突然对cocos2d-x中回调机制很感兴趣,但是之前两周第一次接触实际C++开发,又要学习cocos2d-x框架,还有比较疲劳。实在没有心情去搞这些,这两天偷了个懒,缓了两天,终于又有精神干活了,要写大量的类似大掌门一样的战斗动画播放。我原来的想法是使用大量的回调来控制,因为不同的回合的动画需要的处理是不一样的,动画长短,还有后续的处理方式。后来发觉不现实,大量的回调,会把自己搞得头晕脑胀,根本无法控制流程,灵活性太低,最后决定使用定时去做。

话说回来,今天看到函数指针,突然很感兴趣,于是决定看看这一部分的知识,看看在CCObject中的关于schedule指针的定义

[cpp]  view plain copy
  1. typedef void (CCObject::*SEL_SCHEDULE)(float);  
  2. #define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)  

我得思路一直停留在C语言中的函数指针中,对于&符号的含义非常不清楚,这时候问一个经常使用C++的同学,他也表示很不清楚,大概是对C++的理解,停留在C语言的基础上,这样也有不好的一点,容易固化思维。我也是这样子的,对于传递一个这样一个指针的时候。

[cpp]  view plain copy
  1. void GameFightingLayer::performRoundAnimation(float time)  
  2. this -> schedule(schedule_selector(GameFightingLayer::performAttackAnimation), delay);  

可以发现,这个宏中传递函数指针的时候,需要添加GameFightingLayer作用域,对宏展开之后发现,其实&GameFightingLayer::performAttackAnimation。。。。基于对C语言的了解,不应该这样的,应该是直接GameFightingLayer::performAttackAnimation就是表示函数指针了,为什么还要加一个&符号呢?问同学,他也表示不了解,后来发现。这是一种C++中特有的语法类型。

http://www.parashift.com/c++-faq-lite/fnptr-vs-memfnptr-types.html

这个网站解释的很清楚:

Consider the following function:

int f(char a, float b);
The type of this function is different depending on whether it is an ordinary function or a non- static  member function of some class:
  • Its type is "int (*)(char,float)" if an ordinary function
  • Its type is "int (Fred::*)(char,float)" if a non-static member function of class Fred

Note: if it's a static member function of class Fred, its type is the same as if it were an ordinary function: "int (*)(char,float)".

根据成员方法指针是否是静态而言,如是静态方法,则其类型就可表示为与普通的方法指针相同,如果不是,那么这个方法指针的类型,就跟普通方法指针不一致了,是一种C++特有的语法,跟C不一致。同学跟我解释是,想想一下内存地址的就明白为什么这样了,也是,往往把基本都忘记,如果是静态的,地址空间是固定的,非静态的话,方法地址必定是跟某个class相关的。

后来又发现一个很有意思的问题,在使用这种指针的时候,编译器总是报错,后来偶尔间改了一下空格,发现好。。。。

错的写法: m_pSelectorTarget  ->   *m_pCallFunc 

正确的写法: m_pSelectorTarget  ->*   m_pCallFunc

我习惯性地分割操作符,结果发现总是会有问题,原来->*和.*是操作符,坑爹啊!是C++中的操作符,已经不能按C中的指针的概念理解了。正如msdn中这篇文章的解释一样: 

http://msdn.microsoft.com/en-us/library/k8336763.aspx

其中有一段代码我感觉挺有意思的,除了解释上面的问题之外,还有别的问题帮我解决了

[cpp]  view plain copy
  1. // expre_Expressions_with_Pointer_Member_Operators.cpp  
  2. // compile with: /EHsc  
  3. #include <iostream>  
  4.   
  5. using namespace std;  
  6.   
  7. class Testpm {  
  8. public:  
  9.    void m_func1() { cout << "m_func1\n"; }  
  10.    int m_num;  
  11. };  
  12.   
  13. // Define derived types pmfn and pmd.  
  14. // These types are pointers to members m_func1() and  
  15. // m_num, respectively.  
  16. void (Testpm::*pmfn)() = &Testpm::m_func1;  
  17. int Testpm::*pmd = &Testpm::m_num;  
  18.   
  19. int main() {  
  20.    Testpm ATestpm;  
  21.    Testpm *pTestpm = new Testpm;  
  22.   
  23. // Access the member function  
  24.    (ATestpm.*pmfn)();  
  25.    (pTestpm->*pmfn)();   // Parentheses required since * binds  
  26.                         // less tightly than the function call.  
  27.   
  28. // Access the member data  
  29.    ATestpm.*pmd = 1;  
  30.    pTestpm->*pmd = 2;  
  31.   
  32.    cout  << ATestpm.*pmd << endl  
  33.          << pTestpm->*pmd << endl;  
  34.    delete pTestpm;  
  35. }  

这段代码中, 说明了->*和.*操作符的区别,正如结构体调用时的方式一样

还有一个比较有意思的地方就是,关于成员变量的指针,竟然跟操作成员函数的方式一样。


还有一些关于这个话题比较有意思的讨论,链接如下:

http://stackoverflow.com/questions/2891926/create-thread-is-not-accepting-the-member-function

http://www.parashift.com/c++-faq-lite/memfnptr-vs-fnptr.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值