C ++成员函数表

时间:2012-01-26 17:16:58

标签: c++ arrays data-structures member-function-pointers

我需要一个将代码映射到C ++成员函数的表。假设我们有这个类:

class foo
{
  bool one() const;
  bool two() const;
  bool call(char*) const;
};

我想要的是这样一张桌子:

{
  { “somestring”,  one },
  { ”otherstring”, two }
};

因此,如果我有一个foo对象ff.call(”somestring”)将在表中查找“somestring”,调用one()成员函数,并返回结果

所有被调用的函数都有相同的原型,即它们是const,不带参数,返回bool。

这可能吗?怎么样?

5 个答案:

答案 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::functionstd::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}}构造。