C++成员函数的表

Tables of C++ member functions

本文关键字:函数 成员 C++      更新时间:2023-10-16

我需要一个将代码映射到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。

这可能吗?怎样

是的,可以使用指向成员的指针语法。

使用您提供的原型,地图将是。

std::map< std::string, bool( foo::*)() const>

它将用这种语法称为

this->*my_map["somestring"]();

这个奇怪的->*运算符用于指向成员函数的指针,由于继承的原因,这些函数可能会有一些奇怪的考虑因素。(这不仅仅是一个原始地址,正如->所期望的那样)

由于您只需要存储具有相同参数和返回类型的同一类的成员,因此可以使用指向成员函数的指针:

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。分配:

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(如果您确保数组已排序)查找条目。

是。

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
       }
   }
}

我会选择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

以下是相关文件:

  • 增压功能
  • Boost.Bind

祝你好运!

编辑:关于你关于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();
}

我只想补充一点,如果没有一个类的实例来调用它,指向成员函数的指针是没有意义的。你描述的情况说明了这一点(我想你也知道这一点),但在其他情况下,在某种函子构造中,可能需要用指向函数指针所对应实例的指针或引用来封装函数指针。