我需要一个将代码映射到C ++成员函数的表。假设我们有这个类:
class foo
{
bool one() const;
bool two() const;
bool call(char*) const;
};
我想要的是这样一张桌子:
{
{ “somestring”, one },
{ ”otherstring”, two }
};
因此,如果我有一个foo
对象f
,f.call(”somestring”)
将在表中查找“somestring”,调用one()
成员函数,并返回结果
所有被调用的函数都有相同的原型,即它们是const,不带参数,返回bool。
这可能吗?怎么样?
答案 0 :(得分:6)
是的,可以使用指向成员语法的指针。
使用您提供的原型,地图将是。
std::map< std::string, bool( foo::*)() const>
将使用此语法调用
this->*my_map["somestring"]();
奇怪的->*
运算符用于指向成员函数的指针,由于继承,这可能有一些奇怪的考虑因素。 (它不仅仅是一个原始地址,正如->
所期望的那样)
答案 1 :(得分:3)
是
struct foo_method
{
std::string name;
bool (foo::*pfun)() const;
};
foo_method methodTable[] =
{
{ “somestring”, &foo::one },
{ ”otherstring”, &foo::one }
};
void foo::call(const char* name) const
{
size_t size = sizeof(methodTable)/sizeof(*methodTable);
for(size_t i = 0 ; i < size ; ++i)
{
if ( methodTable[i].name == name )
{
bool (foo::*pfun)() const = methodTable[i].pfun;
(this->*pfun)(); //invoke
}
}
}
答案 2 :(得分:2)
我会boost::function
与std::map
一起去。具体来说,这样的事情:
typedef boost::function<bool()> MyFunc;
typedef std::map<std::string, MyFunc> MyFuncMap;
然后,给定一个MyFuncMap实例,你可以map["something"]()
。然后你可以将它包装在一个重载operator()
的类中。您可以使用函数指针/引用,但我更喜欢使用boost::function
,因为它允许我将指针绑定到成员函数(使用boost :: bind)或使用其他函数对象。您也可以像使用常规函数指针一样在条件句中测试boost::function
。
以下是相关文件:
祝你好运!编辑:关于const成员和boost::function
的问题,这是一个例子:
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function<bool ()> FuncPtr;
struct Test
{
bool test() const
{
std::cout << "yay" << std::endl;
}
};
int main(int argc, char **argv)
{
Test t;
FuncPtr ptr = boost::bind(&Test::test, &t);
ptr();
}
答案 3 :(得分:2)
由于您只需要存储具有相同参数和返回类型的同一类的成员,因此可以使用指向成员函数的指针:
bool foo::call(char const * name) const {
static std::map<std::string, bool (foo::*)() const> table
{
{"one", &foo::one},
{"two", &foo::two}
};
auto entry = table.find(name);
if (entry != table.end()) {
return (this->*(entry->second))();
} else {
return false;
}
}
它使用了C ++ 11的新初始化语法。如果您的编译器不支持它,那么还有其他各种选项。您可以使用静态函数初始化地图:
typedef std::map<std::string, bool (foo::*)() const> table_type;
static table_type table = make_table();
static table_type make_table() {
table_type table;
table["one"] = &foo::one;
table["two"] = &foo::two;
return table;
}
或者您可以使用Boost.Assignment:
static std::map<std::string, bool (foo::*)() const> table =
boost::assign::map_list_of
("one", &foo::one)
("two", &foo::two);
或者您可以使用数组,并找到包含std::find_if
的条目(如果您的库还没有,则可以使用简单的for
循环),或者如果您使用std::binary_search
确定数组已排序。
答案 4 :(得分:1)
我想补充一点,指向成员函数的指针没有意义,没有可以调用它的类的实例。你所描述的情况说明了这一点(我想你知道这一点),但是在其他情况下,可能需要用一个指针或引用来封装函数指针,它指向它所对应的实例{{{ 3}}构造。