我的问题有点复杂,所以我将从一个例子开始:
class a
{
public:
a()
{
pointerMap.insert(pair<std::string, void a::*(int, int)> ("func1", func1);
pointerMap.insert(pair<std::string, void a::*(int, int)> ("func2", func2);
}
private:
void func1(int a, int b);
void func2(int a, int b);
std::map<std::string, void a::* (int, int)> pointerMap;
}
我的问题是,这是将成员函数的指针添加到对象中的地图的正确方法,因此您只引用单个实例的func1
或func2
吗?
而且,我也不知道如何从指针调用此函数。它会是这样的吗?
map["func1"](2,4);
使用成员函数时,我对语法有点困惑。
答案 0 :(得分:7)
首先,代码:
#include <map>
#include <string>
class a
{
public:
a()
{
pointerMap["func1"] = &a::func1;
pointerMap["func2"] = &a::func2;
}
void invoke(const std::string& name, int x, int y) {
if(pointerMap[name])
(this->*pointerMap[name])(x, y);
}
private:
void func1(int a, int b) {};
void func2(int a, int b) {};
std::map<std::string, void (a::*)(int, int)> pointerMap;
};
int main () {
a o;
o.invoke("func1", 1, 2);
}
现在,提出您的问题:
我的问题是,这是将成员函数的指针添加到对象中的地图的正确方法
我发现下标运算符[]
比你正在进行的插入更容易阅读。
这样您只能引用单个实例的func1或func2。
Pointer-to-member-function没有与之关联的实例。在调用实例时将指针绑定到实例。因此,您的地图可能就像一个静态成员一样容易。
我将如何从指针调用此函数。
语法为:(instance.*pointer)(args)
或(class_pointer->*pointer)(args)
。由于您没有说明应该调用哪些函数,我假设this
。你的指针存在于地图中,所以我们有:
((this)->*(this->pointerMap["func1"]))(arg1, arg2)
或
(this->*pointerMap[name])(x, y);
答案 1 :(得分:2)
这是对的。也许一个typedef可以让事情变得更清洁:
typedef std::map<std::string, void(a::*)(int, int)> pfmap_type;
pfmap_type m; // ^^^^^^
// ...
m.insert(pfmap_type::value_type("hello", &a::func1));
// ^^^
(this->*(m["hello"]))(1, 2);
(this->*(m.find("hello")->second))(3, 4);
实际上,两个地图访问都不是一个好主意,因为你绝对必须检查地图项是否存在,否则你会有一个错误的指针。所以我推荐这样的东西:
void call(const char * key, int a, int b) const
{
pfmap_type::const_iterator it = m.find(key);
if (it != m.end()) { (this->*(it->second))(a, b); }
}
答案 2 :(得分:1)
这是将指针插入地图的正确方法,但是你可以使用make_pair
来整理一些东西,这会为你推导出模板参数:
pointerMap.insert(std::make_pair("func1", &func1)); // The '&' is optional
要调用函数,您需要使用.*
或->*
运算符,具体取决于您调用它的对象是否通过指针引用:
a obj; // Regular object
(a .* map["func1")(2, 4); // Extra parens needed due to operator precedence
a *ptr; // Pointer
(a ->* map["func1")(2, 4);
有些人喜欢定义一个宏来让你更清楚你正在做什么,因为语法可能会让一些人感到困惑:
#define CALL_MEMBER_FUN_PTR(obj, fun) ((obj) ->* (fun))
...
a *ptr;
CALL_MEMBER_FUN_PTR(ptr, map["func1"])(2, 4);