I am experimenting around with extending cocos2d-x CCMenuItem components and came across something I have not seen before in C++. It would be helpful if someone would elaborate on what is going on with their function pointer declarations
The base class for most cocos2d-x objects is CCObject which has the following definition
class CC_DLL CCObject : public CCCopying
{
public:
// Code omitted
};
// The part in which I have a question about
typedef void (CCObject::*SEL_SCHEDULE)(float);
typedef void (CCObject::*SEL_CallFunc)();
typedef void (CCObject::*SEL_CallFuncN)(CCNode*);
typedef void (CCObject::*SEL_CallFuncND)(CCNode*, void*);
typedef void (CCObject::*SEL_CallFuncO)(CCObject*);
typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
typedef void (CCObject::*SEL_EventHandler)(CCEvent*);
typedef int (CCObject::*SEL_Compare)(CCObject*);
#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)
#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)
#define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)
#define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)
#define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)
#define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)
#define event_selector(_SELECTOR) (SEL_EventHandler)(&_SELECTOR)
#define compare_selector(_SELECTOR) (SEL_Compare)(&_SELECTOR)
So outside of the CCObject class, but within the cocos2d namespace, there exists a declaration for function pointers and helper macros to use them. Am I correct in calling these declarations for function pointers?
I understand that typedef is associating a keyword with a type (See Typedef function pointer?) and that the return type is must be void and the function must have one mandatory argument of CCObject *. However I am lost in understanding its appropriate usage, scope, and how C++ treats passing a function through another function.
Question 1
I am not following how to interpret the scope of the declared function pointer. In their declaration, they show the function pointer being scoped by the CCObject class. How should I interpret this? Does this mean when it is assigned that function belongs as a member function to CCObject? This is confusing to me as it is defined outside of the class body but scoped with CCObject.
typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
Question 2
In the cocos2d-x CCMenuItem class, it has a static factory method defined below
// How does C++ treat the this? Is a function treated like an object here?
static CCMenuItem* create(CCObject *rec, SEL_MenuHandler selector);
CCMenuItem* CCMenuItem::create(CCObject *rec, SEL_MenuHandler selector)
{
CCMenuItem *pRet = new CCMenuItem();
pRet->initWithTarget(rec, selector);
pRet->autorelease();
return pRet;
}
bool CCMenuItem::initWithTarget(CCObject *rec, SEL_MenuHandler selector)
{
setAnchorPoint(ccp(0.5f, 0.5f));
m_pListener = rec;
m_pfnSelector = selector;
m_bEnabled = true;
m_bSelected = false;
return true;
}
// A snippet from CCMenuItem header
protected:
CCObject* m_pListener;
SEL_MenuHandler m_pfnSelector; // member variable which stores a pointer to a function?
int m_nScriptTapHandler;
};
So does this typedef mean that when I pass a function it, I am passing by value with a pointer? How would C++ handle this if the function was not passed by pointer. Is a function treated like an object with a copy constructor?
I appreciate any help and advice. Thanks
void (CCObject::*)(CCObject*)
is a method pointer type (one type of pointer to member), not an ordinary function pointer. It's a pointer that can point to an instance method of the CCObject
class that takes a parameter of CCObject*
type. The type of class it's a method of is part of the pointer type (denoted by the CCObject::
), similar to the parameters (because underneath, a pointer to the "current object" is a hidden parameter to all instance methods, this
).
The typedef
simply defines SEL_MenuHandler
to be a synonym for that method pointer type.
To use a method pointer, you need to provide both an instance to act as this
, as well as the arguments, using a syntax like this:
CCObject* object;
CCObject* anotherObject;
SEL_MenuHandler methodPointer;
(object->*methodPointer)(anotherObject);
// or equivalently: ((*object).*methodPointer)(anotherObject);
How would C++ handle this if the function was not passed by pointer. Is a function treated like an object with a copy constructor?
In C/C++, it is not possible to have an expression of "function type" or "method type". Any time you try to get something of "function type", it is automatically converted to a "pointer to function" type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With