类成员函数指针 ->*语法剖析
在cocos2d-x中,经常会出现这样的调用,如 ->*,这个是什么意思呢,如下面得这个例子:
,
其实这是对类的成员函数指针的调用,在cocos2dx中,这种形式多用于回调函数的调用。如我们经常用到的循环函数
schedule( CC_SCHEDULE_SELECTOR(PauseTest::unpause), 3);
这个意思就是每隔3秒,执行一下unpause方法,这里就用到了成员函数指针,先看下CC_SCHEDULE_SELECTOR的宏定义
#define CC_SCHEDULE_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)
就是把传入的函数,然后取其地址,转换为 SEL_SCHEDULE,那么SEL_SCHEDULE是什么呢,转到其定义处,为
typedef void (Ref::*SEL_SCHEDULE)(float);
就是说他就是一个指向参数为float,返回值为void 的函数指针,注意他和一般c语言的函数指针不同的是,前面加了作用域Ref,在后面会讲解一般函数指针和类函数指针的不同,这里先看作用域为什么是Ref,以为cocos2d所有的类都继承自Ref,所以只要是cocos2d的类,就可以作为SEL_SCHEDULE的target,深入到schedule( CC_SCHEDULE_SELECTOR(PauseTest::unpause), 3); 的里面,就会发现,是这么调用的

,_selector就是回到函数的地址,_target就是要调用这个回调函数的基类为Ref的对象指针,当每次循环的时候,就会这么调用

从而实现了指定的target进行函数的回调.
现在用一个demo简单演示一下他的用法
namespace AB {
class A ;
typedef void (A::*SEL_CallJinLei)();
class A
{
public:
A(){}
virtual void testA();
};
void A::testA(){
printf("A的testA");
}
class ChildrenA: public A{
public:
virtual void testA(){
printf("ChildrenA的testA");
}
};
class B
{
public:
B(){
}
B(A*target,SEL_CallJinLei selector){
_target=target;
_selector=selector;
}
A *_target;
SEL_CallJinLei _selector;
void testB(){
(_target->*_selector)();
}
};
}
void main(){
using namespace AB;
AB::A *aaa=new A();
ChildrenA *aaa2=new ChildrenA();
B *bbb=new B(aaa,static_cast<AB::SEL_CallJinLei>(&A::testA));
bbb->testB();
B *bbb2=new B(aaa2,static_cast<AB::SEL_CallJinLei>(&ChildrenA::testA));
bbb2->testB();
}
Class A和Class ChildrenA都是我们指的target,他们有成员函数指针,当确定了函数指针的指向,就可以用target来调用了,
通过main中的调用也可以看出, Class A和Class ChildrenA都可以使用
SEL_CallJinLei,也就是实现了多态特性 在cocos2dx中应用也就是 testB就是执行了某些逻辑之后,触发的方法,如scheduler中的trigger,触发之后,就会调用target->*函数指针,从而实现了target的回调方法 下面是解释一般函数指针和成员函数指针的区别,这个网上也比较多了,这里引用一篇,
原文地址为http://www.jb51.net/article/40718.htm
函数指针是通过指向函数的指针间接调用函数。函数指针可以实现对参数类型、参数顺序、返回值都相同的函数进行封装,是多态的一种实现方式。由于类的非静态成员函数中有一个隐形的this指针,因此,类的成员函数的指针和一般函数的指针的表现形式不一样。
1、指向一般函数的指针
函数指针的声明中就包括了函数的参数类型、顺序和返回值,只能把相匹配的函数地址赋值给函数指针。为了封装同类型的函数,可以把函数指针作为通用接口函数的参数,并通过函数指针来间接调用所封装的函数。
下面是一个指向函数的指针使用的例子。
/*指向函数的指针*/
typedef int (*pFun)(int, int);
int Max(int a, int b)
{
return a > b ? a : b;
}
int Min(int a, int b)
{
return a < b ? a : b;
}
/*通用接口函数,实现对其他函数的封装*/
int Result(pFun fun, int a, int b)
{
return (*fun)(a, b);
}
void main()
{
int a = 3;
int b = 4;
cout<<"Test function pointer: "<<endl;
cout<<"The maximum number between a and b is "<<Result(Max, a, b)<<endl;
cout<<"The minimum number between a and b is "<<Result(Min, a, b)<<endl;
}
2、指向类的成员函数的指针
类的静态成员函数采用与一般函数指针相同的调用方式,而受this指针的影响,类的非静态成员函数与一般函数指针是不兼容的。而且,不同类的this指针是不一样的,因此,指向不同类的非静态成员函数的指针也是不兼容的。指向类的非静态成员函数的指针,在声明时就需要添加类名。
下面是一个指向类的成员函数的指针的使用的例子,包括指向静态和非静态成员函数的指针的使用。
class CA;
/*指向类的非静态成员函数的指针*/
typedef int (CA::*pClassFun)(int, int);
/*指向一般函数的指针*/
typedef int (*pGeneralFun)(int, int);
class CA
{
public:
int Max(int a, int b)
{
return a > b ? a : b;
}
int Min(int a, int b)
{
return a < b ? a : b;
}
static int Sum(int a, int b)
{
return a + b;
}
/*类内部的接口函数,实现对类的非静态成员函数的封装*/
int Result(pClassFun fun, int a, int b)
{
return (this->*fun)(a, b);
}
};
/*类外部的接口函数,实现对类的非静态成员函数的封装*/
int Result(CA* pA, pClassFun fun, int a, int b)
{
return (pA->*fun)(a, b);
}
/*类外部的接口函数,实现对类的静态成员函数的封装*/
int GeneralResult(pGeneralFun fun, int a, int b)
{
return (*fun)(a, b);
}
void main()
{
CA ca;
int a = 3;
int b = 4;
cout<<"Test nonstatic member function pointer from member function:"<<endl;
cout<<"The maximum number between a and b is "<<ca.Result(CA::Max, a, b)<<endl;
cout<<"The minimum number between a and b is "<<ca.Result(CA::Min, a, b)<<endl;
cout<<endl;
cout<<"Test nonstatic member function pointer from external function:"<<endl;
cout<<"The maximum number between a and b is "<<Result(&ca, CA::Max, a, b)<<endl;
cout<<"The minimum number between a and b is "<<Result(&ca, CA::Min, a, b)<<endl;
cout<<endl;
cout<<"Test static member function pointer: "<<endl;
cout<<"The sum of a and b is "<<GeneralResult(CA::Sum, a, b)<<endl;
}
类成员函数指针 ->*语法剖析的更多相关文章
- C++的类成员和类成员函数指针
类成员函数指针: 用于访问类成员函数,和一般函数指针有区别. 类成员函数处理的是类数据成员,声明类成员函数指针的同时,还要指出具体是哪个类的函数指针才可以.调用时也要通过对象调用. 而对于类的静态成员 ...
- C/C++ 类成员函数指针 类成员数据指针
普通函数指针: "return_type (*ptr_name)(para_types) " 类成员函数指针: "return_type (class_name::*p ...
- C++函数指针和类成员函数指针
一.函数指针——基本形式 char Fun(int n) { return char(n); } //char(*pFun)(int); void main() { char(*pFun)(int); ...
- 类成员函数指针的特殊之处(成员函数指针不是指针,内含一个结构体,需要存储更多的信息才能知道自己是否virtual函数)
下面讨论的都是类的非静态成员函数. 类成员函数指针的声明及调用: 1 2 3 4 5 6 7 //pr是指向Base类里的非静态成员函数的指针 //其行参为(int, int),返回值为void vo ...
- 使用std::function 把类成员函数指针转换为普通函数指针
前言 这是改造前一篇 设计模式 的基础,使通知者不必知道观察者的类名和函数名,只需要知道更新函数的原型即可. 开发环境:WIN7 32位 + VS2010 发现在VS2005中使用std::funti ...
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- 成员函数指针与高效C++委托 (delegate)
下载实例源代码 - 18.5 Kb 下载开发包库文件 - 18.6 Kb 概要 很遗憾, C++ 标准中没能提供面向对象的函数指针. 面向对象的函数指针也被称为闭包(closures) 或委托(del ...
- 成员函数指针与高性能C++委托
1 引子 标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做“闭包(closure)”或“委托(delegate)”)在一些语言中已经证明了它宝贵的价值. ...
- [转]成员函数指针与高性能的C++委托
原文(作者:Don Clugston):Member Function Pointers and the Fastest Possible C++ Delegates 译文(作者:周翔): 成员函数指 ...
随机推荐
- thymeleaf之fragment
MUEAS项目,web前端采用thymeleaf作为展示层.这个view解析器,个人觉得非常不错.简单而且性能也比较好!个人觉得比JSP和freemarker之类,简单易用! 今天简单记录一下frag ...
- java hashtable
java hashtable Hashtables提供了一个很有用的方法可以使应用程序的性能达到最佳. Hashtables(哈希表)在计算机领域中已不 是一个新概念了.它们是用来加快计算机的处理速度 ...
- Hibernate3回顾-3-Session管理
3.Session管理 仅为个人理解.请指正 3.1背景 由于Configuration的创建耗费系统的资源.所以有必要只将Configuration实例化一次,之后通过SessionFactory获 ...
- 【原】Centos 7 下创建LVM流程
阅读目录 个主分区,1个扩展分区] 或 [4个主分区],扩展分区又可以有多个分区: window常见的分配方式: 方式1:[1个主分区(C盘)+1个扩展分区(包括3个分区,D,E, ...
- 利用maven的filter和profile实现不同环境使用不同的配制
在我们平常的java开发中,会经常使用到很多配制文件(xxx.properties,xxx.xml),而当我们在本地开发(dev),测试环境测试(test),线上生产使用(product)时,需要不停 ...
- CRT:C运行库简介
1)运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的"小内核&q ...
- SNM2无法编辑HostGroup项
经常遇到SNM2的工具无法更新,无法编辑,或者加载急慢的情况.解决方法就是在SNM2重新添加Array,然后再重新登录试试
- Linux系统默认服务建议开启关闭说明列表
服务名称 功能简介 建议 acpid 电源管理接口.如果是笔记本用户建议开启,可以监听内核层的相关电源事件. 开启 anacron 系统的定时任务程序.cron的一个子系统,如果定时任务错过了执行时间 ...
- Redis容量及使用规划(转)
在使用Redis过程中,我们发现了不少Redis不同于Memcached,也不同于MySQL的特征. (本文主要讨论Redis未启用VM支持情况) 1. Schema MySQL: 需事先设计Memc ...
- 手把手教你玩转Git分布式版本控制系统! (转载)
目录 Git诞生历史 Git环境准备 Git安装部署 Git常用命令 Git基本操作 Git管理分支结构 Git管理标签 GitLab安装部署 GitHub托管服务 Git客户端工具 Git诞生历史 ...