函数指针一般来说必须返回类型和参数类型一一严格对应,否则有可能导致问题,即使参数类型本身是父子关系。
比如如果想自定义一个通知对象来取代通知回调函数中CCObject参数:
typedef void (CCObject::*SEL_NotifyFunc)(NotificationObj*);
class NotificationObj : public CCObject {
public:
NotificationObj(void *data) { this->data = data; }
void *data;
};
class MyMsgCenter : public GameCenter, CCObject { // 一时疏忽,忘记给CCObject加上puclic了
public:
MyMsgCenter();
void MyMsgCenter::handleLogic(NotificationObj *obj); // NotificationObj继承CCObject
}
MyMsgCenter::MyMsgCenter() {
NotificationCenter* center = CCNotificationCenter::sharedNotificationCenter();
center->addObserver(this, callfuncO_selector(MyMsgCenter::handleLogic), "xxx", NULL); // 直接强制转换
}
真正运行接收通知的时候,诡异问题出现了,发现自动(暗地里)产生了另外一个MyMsgCenter对象, 由于CCObject是以私有继承方式继承,编译器这时候处理的时候认为当前的MyMsgCenter对象也许不是最适合的处理对象,就给你创造了一个临时的对象出来了。
如果改成 class MyMsgCenter : public GameCenter, public CCObject 是没有问题的。另外,不修改public,也可以这样达到正确的目的:
center->addObserver(this, (SEL_CallFuncO)((SEL_NotifyFunc)(&MyMsgCenter::handleLogic)), "xxx", NULL);
经过两次转换之后,不再自动产生MyMsgCenter对象了,也就是你已经显示的告知编译器我这个函数是长什么样了。