【问题标题】:Map to method c++11映射到方法 c++11
【发布时间】:2016-04-07 11:01:56
【问题描述】:

我尝试使用 C++11 的 function 映射到类方法。

C-Style 函数指针:
方法:

void MyClass::MyMethod(void*);

地图声明:

std::map<int, void (MyClass::*)(void*)> mapIdToMethod;

地图插入:

mapIdToMethod.insert(std::make_pair(2, &MyClass::MyMethod));

方法调用:

MyClass mc;
(mc.*mapIdToMethod.at(1))(nullptr);

上面的代码是可以工作的,但是我怎样才能将它转换为使用 C++11 的function
我尝试了什么:
地图声明:

std::map<int, function<void(void*)>> mapIdToMethod;//The map declare

现在,我如何在这个map 上插入和调用方法?

【问题讨论】:

  • 如果您拥有的代码没有任何问题,请保留它。 如果没有损坏,请不要修复它
  • std::function 是另一回事。您的原始代码仅存储成员函数指针。 std::function 要求成员函数指针绑定到类的实例。
  • 如果函数 MyMethod 使用了一些内部状态,你可能需要 bind 它,或者使用 lambda。但正如@bolov 所说,如果它有效,你不应该修改它。至少因为 std::function 会给它带来运行时开销,所以就这样吧。
  • 您在此处展示的两张地图用于完全不同的目的。一个持有指向成员函数的指针,这需要调用实例;另一个是完全绑定函数对象的容器。您想在新方法中存储绑定函数吗?
  • mapIdToMethod.insert(std::make_pair(2, &amp;MyClass::MyMethod)); 在 c++11 中可以重写为 mapIdToMethod.emplace(2, &amp;MyClass::MyMethod);

标签: c++ function c++11 dictionary member-function-pointers


【解决方案1】:

可能不如原版高效,但可能更易于阅读:

std::map<int, std::function<void (MyClass&,void*)>> mapIdToMethod;    
mapIdToMethod.emplace(2, [](MyClass& c,void* p){ c.MyMethod(p);});
// alternatively:
using std::placeholders::_1;    
using std::placeholders::_2;
mapIdToMethod.emplace(2,std::bind(&MyClass::MyMethod,_1,_2));

MyClass mc;
mapIdToMethod.at(2)(mc, nullptr);

【讨论】:

  • 不,阅读起来并不容易。使用 C++11 功能绝对很酷,但一点也不容易阅读。
  • 鉴于 OP 有 C++11,您可以使用 std::bindstd::placeholders::_1
  • @juanchopanza:我同意。
  • emplace 将提高可读性并摆脱std::make_pair
【解决方案2】:

我也是 function 而非 C 风格指针的粉丝,但重要的是您要认识到 void (MyClass::*)(void*) 的模拟是 function&lt;void(MyClass&amp;, void*)&gt; 不是 function&lt;void(void*)&gt;。所以你可以复制你已经在MapIdToMethod 中的内容:

map<int, function<void(MyClass&, void*)>> bar;

您可以像插入到MapIdToMethod (bar.insert(make_pair(2, &amp;MyClass::MyMethod)) 一样插入到这里,但您也可以使用mem_fn,在插入到MapIdToMethod 时无法使用:

bar.insert(make_pair(2, mem_fn(&MyClass::MyMethod)));

现在,回答您的问题。给定:

map<int, function<void(void*)>> foo;

您可以插入接受void* 并且不返回任何内容的成员函数,但前提是您已经拥有要在其上构建调用的对象。你可以使用bind

MyClass mc;

foo.insert(make_pair(2, bind(&MyClass::MyMethod, mc, placeholders::_1)));

Live Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-28
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2015-08-21
    • 1970-01-01
    相关资源
    最近更新 更多