简体   繁体   English

C ++成员函数表

[英]Tables of C++ member functions

I need a table that maps codes to C++ member functions. 我需要一个将代码映射到C ++成员函数的表。 Suppose we have this class: 假设我们有这个类:

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

What I want is a table like this: 我想要的是这样的一张桌子:

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

So that if I have a foo object f , f.call(”somestring”) would look up “somestring” in the table, call the one() member function, and return the result. 这样,如果我有一个foo对象ff.call(”somestring”)将在表中查找“ somestring”,调用one()成员函数,然后返回结果。

All of the called functions have identical prototypes, ie, they are const, take no parameters, and return bool. 所有被调用的函数都具有相同的原型,即它们是const,不带参数并返回bool。

Is this possible? 这可能吗? How? 怎么样?

Yes, it's possible, using pointer to member syntax. 是的,可以使用指向成员语法的指针

Using the prototypes you supplied, the map would be. 使用您提供的原型,地图就可以了。

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

It would be called with this syntax 将使用这种语法来调用

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

That odd-looking ->* operator is for pointer to member functions, which can have some odd considerations, due to inheritance. 看起来很奇怪的->*运算符用于指向成员函数的指针,由于继承,它们可能具有一些奇怪的注意事项。 (It's not just a raw address, as -> would expect) (不只是原始地址,正如->所期望的那样)

Yes. 是。

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

I would go with boost::function with std::map . 我会使用带有std::map boost::function Concretely, something like this : 具体来说,是这样的:

typedef boost::function<bool()> MyFunc;
typedef std::map<std::string, MyFunc> MyFuncMap;

Then, given an instance of MyFuncMap, you could just do map["something"]() . 然后,给定MyFuncMap的实例,您可以执行map["something"]() Then you could wrap that in a class that overloads operator() . 然后,您可以将其包装在一个重载operator()的类中。 You could use function pointers/references, but I prefer using boost::function because it allows me to bind pointers to member functions (using boost::bind) or use other function objects. 您可以使用函数指针/引用,但是我更喜欢使用boost::function因为它允许我将指针绑定到成员函数(使用boost :: bind)或使用其他函数对象。 You can also test boost::function in conditionals as you would with regular function pointers. 您也可以像使用常规函数指针一样在条件条件下测试boost::function

Here is the relevant documentation : 以下是相关文档:

Good luck! 祝好运!

Edit: Regarding your question about the const member and boost::function , here's an example : 编辑:关于您的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();
}

Since you only need to store members of the same class, with the same arguments and return types, you can use pointer-to-member-functions: 由于您只需要存储具有相同参数和返回类型的相同类的成员,因此可以使用指向成员函数的指针:

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

That uses the new initialisation syntax of C++11. 这使用了C ++ 11的新初始化语法。 If your compiler doesn't support it, there are various other options. 如果您的编译器不支持它,则还有其他各种选择。 You could initialise the map with a static function: 您可以使用静态函数初始化地图:

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

or you could use Boost.Assignment : 或者你可以使用Boost.Assignment

static std::map<std::string, bool (foo::*)() const> table = 
    boost::assign::map_list_of
        ("one", &foo::one)
        ("two", &foo::two);

or you could use an array, and find the entry with std::find_if (or a simple for loop if your library doesn't have that yet), or std::binary_search if you make sure the array is sorted. 或者您可以使用一个数组,并使用std::find_if (或一个简单的for循环,如果您的库还没有,则使用一个简单的for循环)查找条目,或者如果您确保对数组进行了排序,则使用std::binary_search

I'd just like to add that a pointer to a member function is meaningless without having an instance of a class on which to call it. 我只想补充一点,没有成员类调用实例的成员函数指针是没有意义的。 The situation you've described accounts for this (and I think you know this), however in other situations, it may be necessary to encapsulate the function pointer with a pointer or reference to the instance to which it corresponds in some sort of functor construct. 您所描述的情况是造成这种情况的原因(我想您知道这一点),但是在其他情况下,可能有必要在某种函子构造中使用指向其所对应实例的指针或引用来封装函数指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM