我想存储一个指向对象的指针和一个指向它的已知签名方法的指针。如果我知道该类,则此指针具有类型:
int (MyClass::*pt2Member)(float, char, char)
但是,如果我不知道类型,如何存储指针?
我想做这样的事情:
myObject.callThisFuncLater(&otherObject, &otherObject::method)
如何存储指向方法的指针method
并myObject
稍后调用它?
我想存储一个指向对象的指针和一个指向它的已知签名方法的指针。如果我知道该类,则此指针具有类型:
int (MyClass::*pt2Member)(float, char, char)
但是,如果我不知道类型,如何存储指针?
我想做这样的事情:
myObject.callThisFuncLater(&otherObject, &otherObject::method)
如何存储指向方法的指针method
并myObject
稍后调用它?
如果您可以访问 TR1 STL 库扩展(在 gcc 和 Visual Studio 2008 及更高版本上可用),最简单的方法是。std::function 和 std::bind 可用于包装可以稍后调用的调用。此功能在 boost 函数和 boost 绑定中也可用:
#include <functional>
class MyClass {
public:
template<typename T> callThisFuncLater(T& otherObject,
int(T::*)(float, char, char) method) {
return storedInvocation_ = std::bind(otherObject,
method,
std::placeholders::_1, // float
std::placeholders::_2, // char
std::placeholders::_3); // char
}
int callStoredInvocation(float a, char b, char c) {
storedInvocation_(a, b, c);
}
private:
std::function<int(float, char, char)> storedInvocation_;
};
没有像最初内置在语言或标准库中那样简单的方法来执行此操作(尽管最近已添加)。如果您熟悉 Boost,它们包含一个解决方案 - Boost.Function。
但是,如果由于某种原因,您不能或不愿意使用 Boost,则可以使用模板来执行此操作(诚然,这与 Boost 的解决方案非常相似):
class FncPtr
{
public:
virtual int call(float, char, char) = 0;
};
template <typename T>
class ClassFncPtr : public FncPtr
{
int (T::*pt2Member)(float, char, char);
T *inst;
public:
ClassFncPtr(T* who, int (T::*memfunc)(float,char,char))
: inst(who), pt2Member(memfunc)
{
}
int call(float a, char b, char c)
{
return (inst->*pt2Member)(a,b,c);
}
};
template <typename T>
FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char))
{
return new ClassFncPtr<T>(who,memfunc);
}
如果您愿意,您还可以子类FncPtr
化以便能够使用非类函数。
您可以使用boost::function
(and boost::bind
) 来存储一段代码以供以后调用。
class MyClass
{
public:
void callThisFuncLater( boost::function< int (float, char, char) > callBack );
};
...
myObject.callThisFuncLater( boost::bind( &otherObject::method, &otherObject ) );
我个人会选择不同的设计。仅仅是因为 C++ 中的成员函数指针不容易使用。就我个人而言,我会选择使用接口并从这些接口继承并沿着这些接口进行解析。
成员函数指针的问题之一是它们在不同编译器上的实现方式不同。如果您使用 Borland/Embarcardero 编译器并希望限制自己,您可以使用__closure
关键字,但很可能您不是,因此您必须使用其他一些编译器特定的实现,或者使用 boost 助手之一类之类的函数。
但是,如果您发现在 C++ 中使用成员函数指针很有帮助,请重新考虑您的设计。