我有一个std :: map,我正在尝试存储值的void指针。问题是,我试图存储的大部分指针都是类中的方法,并且具有不同数量的参数。我知道对于params我可以使用一个va列表,所以这不是一个问题,问题是实际的指针本身。
这就是我所拥有的:
class A
{
public:
A();
void methodA(...);
};
class B
{
public:
B();
void methodB(...);
};
void method_no_class(...) { }
std::map<int, void(*)(...)> my_map;
my_map[0] = &method_no_class;
B* cb = new B();
my_map[1] = &cb->methodB; // will return error
答案 0 :(得分:3)
也许这些信息可以帮到你:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
指向方法的指针与指向函数的指针的类型不同。如果您想将它们存储在单个集合中,则必须进行手动转换。
答案 1 :(得分:1)
干净的OO方式是定义命令接口。该接口将采用实例(A
或B
)和所有参数。在invoke()
方法中,它将调用实例的方法。
然后,您可以使用这些命令接口的映射(只需为它们定义一个定义抽象invoke()
方法的公共子类)。编译器会为您检查所有类型和参数,您不必使用varargs。
答案 2 :(得分:0)
你应该在这里使用functionoids。它们可以用作具有不同签名的函数指针的灵活且类型安全的替代。需要一个抽象基类。它包含带有公共参数的实际函数调用,如果有的话。
class Functioniod: public YourClass {
virtual void execute(char d, common_parameters,...) = 0
}
对于要使用的每个函数,都可以创建派生类。构造函数包含特定于函数的参数,而execute()函数包含实际调用。稍后调用此执行函数而不是函数指针。它需要在每个functionoid中具有相同的签名。当然,它也可以在任何其他类别中调用不同的东西。
class FuncA: public Functionoid {
FuncA(int _a, float _b, string _c, function-specific-parameters...) {
a = _a; b = _b; c = _c;
}
void execute(char d, common-parameters,...) {
call-to-member(d, a, b, c);
}
int a;
float b;
string c;
}
现在,如果你想用它来代替你的成员函数指针,你可以这样做:
std::map<int, *Functionoid> my_map;
my_map[0] = new FuncA(someInt, someFloat, someString);
my_map[1] = new FuncB(some-other-parameters...);
并使用
执行它们my_map[0]->execute(common-parm);
my_map[1]->execute(common-parm);
答案 3 :(得分:0)
关于Kamil Szot的回答,C ++常见问题解答(和book)是对C ++和面向对象编程的深层次的一个很好的参考。第33节具体说明了您遇到的问题:
在C ++中,成员函数有一个指向对象的隐式参数(成员函数内的this指针)。普通的C函数可以被认为具有与成员函数不同的调用约定,因此它们的指针类型(指向成员函数的指针与指向函数的指针)是不同的并且不兼容。
当然,你问题的answer有点缺乏细节。
答案 4 :(得分:0)
答案 5 :(得分:-1)
这是一个让您入门的示例代码。没有编译它,所以可能需要一些调整。
#define func(Instance,Method,Class) \
(__int64(Instance)<<32 + __int64(&Class::Method))
#define invoke(Func,Method,Class) \
invoke1(Func,(Class*)0)->*invoke2(Func,&Class::Method)
template<class Class>
Class* invoke1(__int64 Func,Class*)
{
return (Class*)(int)(Func>>32);
}
template<class Method>
Method invoke2(__int64 Func,Method)
{
return (Method)(int)Func;
}
------------ USAGE ------------
class B
{
void methodB(int a,float b){}
};
std::map<int, __int64> my_map;
my_map[0] = func(cb,methodB,B);
invoke(my_map[0],methodB,B)(1,2.f);