【问题标题】:C++ map of "events" and member function pointers“事件”和成员函数指针的 C++ 映射
【发布时间】:2013-10-12 02:17:51
【问题描述】:

我已经设法编写了一个模板类来像回调一样工作,这是从这个问题How to define a general member function pointer 的公认答案中学到的。

我希望有一个字符串键和回调值的映射,以便我可以调用与字符串匹配的正确回调。这很好,但我需要地图来支持来自不同类的回调。现在它只能与一个类一起工作。由于模板,它可以是任何类,但只能是来自同一类的回调集合。

class Apple {
public:
    void Red () {
        cout << "aa";
    }
};

class Orange {
public:
    void Blue () {
        cout << "bb";
    }
};

template <typename T>
class Callback {
    T *obj;
    void (T::*ptr) (void);

public:
    Callback (T *obj, void (T::*ptr) (void)) : obj (obj), ptr (ptr) {

    }

    void Call () {
        (obj->*ptr) ();
    }
};

我可以这样使用

Apple apple;
Orange orange;
Callback <Apple> callA (&apple, &Apple::Red);
Callback <Orange> callB (&orange, &Orange::Blue);
callA.call ();
callB.call ();

std::map <std::string, Callback <Apple>> appleCallbacks;

我希望能够做到这一点

std::map <std::string, Callback <anything>> anyCallbacks;

我打算将它与共享相同基类的一堆类一起使用,并且除了名称和所属的类之外,它们的功能在定义上彼此相同。

class Base { };

class ChildA : public Base {
public:
    void Talk ();
}

class ChildB : public Base {
public:
    void Walk ();
}

因此,如果这可行,我将能够将 Talk () 和 Walk () 都放入地图中。

这有可能吗,还是我的观点一开始就有缺陷?

【问题讨论】:

    标签: c++ templates callback function-pointers member-function-pointers


    【解决方案1】:

    疯狂之处在于:不要将回调绑定到特定的类。而是使用std::function&lt;Signature&gt;对象并创建合适的函数对象:当需要对不同的类进行操作时,也需要对不同类型的对象进行操作。使用 std::function&lt;...&gt; 应该可以解决问题,例如:

    std::map<std::string, std::function<void()>> operations;
    operations["talk"] = std::bind(&ChildA::Talk, ChildA());
    operations["walk"] = std::bind(&ChildB::Walk, ChildB());
    operations["talk"]();
    

    【讨论】:

      【解决方案2】:

      这里不需要继承。只需使用std::function 存储成员函数指针,使用std::bind 将成员函数指针和对象实例绑定在一起即可。

      #include <functional>
      #include <map>
      #include <string>
      #include <iostream>
      
      struct Apple {
          void Red () {
              std::cout << "aa\n";
          }
      };
      
      struct Orange {
          void Blue () {
              std::cout << "bb\n";
          }
      };
      
      int main()
      {
          std::map<std::string, std::function<void()>> m;
          Apple a;
          Orange o;
      
          m["apple"] = std::bind(&Apple::Red, a);
          m["orange"] = std::bind(&Orange::Blue, o);
      
          m["apple"]();
          m["orange"]();
      }
      

      输出:

      aa
      bb
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多