Reputation: 13033
I have following situation, there are two interfaces:
interface ILLShapeAttribute
{
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
};
interface ILLShapeNotification
{
virtual bool IsUsed(const RECT& rcBounds) = 0;
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
}
And 2 functions:
INT LlShapeGetAttributeList(LPCWSTR pwszShapefileName, ILLShapeAttribute* pIAttrInfo);
INT LlShapeEnumShapes(LPCWSTR pwszShapefileName, ILLShapeNotification* pIInfo);
In those both functions I want to call the same function IterateRecords2
which should get the pointer to the function DefineAttribute, e.g. ILLShapeAttribute::DefineAttribute
and ILLShapeNotification::DefineAttribute
I defined it this way:
void IterateRecords2(ifstream& file, void (*pDefineAttribute)(const char*, VARIANT*))
{
pDefineAttribute(NULL, NULL); //will be called with real values
}
Until now the code compiles and everythig is fine. But then I try to call the IterateRecords2
like
IterateRecords2(file, pIAttrInfo->DefineAttribute);
or
IterateRecords2(file, pIInfo->DefineAttribute);
I get the compiler error:
error C3867: 'ILLShapeAttribute::DefineAttribute': function call missing argument list; use '&ILLShapeAttribute::DefineAttribute' to create a pointer to member
Please: I know, that ILLShapeNotification could inherit from ILLShapeAttribute and then pass *ILLShapeAttribute instead of function pointer but I want to understand how it works.
Question: how can I pass the pointer to DefineAttribute
to IterateRecords2
?
Upvotes: 1
Views: 2476
Reputation: 171263
Question: how can I pass the pointer to
DefineAttribute
toIterateRecords2
?
You can't.
A pointer-to-member-function is not compatible with a pointer to function, and even if it was, you'd need an object to call it on, you can't just call a member function without an object.
Some options are:
1) Take a pointer-to-member-function and pass an object.
This would solve your compiler error, but to be able to pass different types of object that are not related by inheritance you would need IterateRecords2
to be a template:
template<typename T>
void IterateRecords2(ifstream& file, T* obj, void (T::*pDefineAttribute)(const char*, VARIANT*))
{
obj->pDefineAttribute(NULL, NULL);
}
Now you can use it like this:
IterateRecords2(file, pIAttrInfo, &ILLShapeAttribute::DefineAttribute);
or:
IterateRecords2(file, pIInfo, &ILLShapeNotification::DefineAttribute);
2) Bind an object and its member function into a callable type, and pass that:
void IterateRecords2(ifstream& file, std::function<void(const char*, VARIANT*)> DefineAttribute)
{
DefineAttribute(NULL, NULL);
}
Then call it like:
IterateRecords2(file, std::bind(&ILLShapeAttribute::DefineAttribute, pIAttrInfo));
If you can't use std::function
and std::bind
you can replace them with boost::function
and boost::bind
Upvotes: 2