【问题标题】:c++ store a pointer to a member function of unknown classc ++存储指向未知类成员函数的指针
【发布时间】:2011-10-16 19:33:23
【问题描述】:

我想存储一个指向对象的指针和一个指向它的已知签名方法的指针。如果我知道该类,则此指针具有类型:

int (MyClass::*pt2Member)(float, char, char)

但是如果我不知道类型如何存储指针呢?

我想做这样的事情:

myObject.callThisFuncLater(&otherObject, &otherObject::method)

如何在myObject 中存储指向方法method 的指针并稍后调用它?

【问题讨论】:

  • @DeadMG:给他们看 :) 我的计数器被困在 2,178,933 个问题上
  • 以后调用时会使用什么参数?
  • @Beta:有关系吗?例如 3.5f, 'a', 'b'
  • 如果参数列表是(float, char, char),这将起作用,但在运行时可能会有所不同。即使您存储了签名,调用代码如何知道要传递哪些值?换句话说,你打算如何使用它?
  • @Beta:我不认为这可以解决这个问题,因为要传递的值取决于 MyClass 逻辑并且仅依赖于它。

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


【解决方案1】:

如果您可以访问 TR1 STL 库扩展(在 gcc 和 Visual Studio 2008 及更高版本上可用),那么最简单的方法是。std::function 和 std::bind 可用于包装可以是稍后调用。此功能在 boost 函数和 boost 绑定中也可用:

#include <functional>

class MyClass {
public:
  template<typename T> callThisFuncLater(T& otherObject,
                                         int(T::*)(float, char, char) method) {
    return storedInvocation_ = std::bind(otherObject, 
                                  method, 
                                  std::placeholders::_1,   // float
                                  std::placeholders::_2,   // char
                                  std::placeholders::_3);  // char
  }

  int callStoredInvocation(float a, char b, char c) {
    storedInvocation_(a, b, c);
  }

private:
  std::function<int(float, char, char)> storedInvocation_;
};

【讨论】:

    【解决方案2】:

    没有简单的方法可以像最初内置在语言或标准库中那样(尽管最近已添加)。如果您熟悉 Boost,他们会为此提供解决方案 - Boost.Function

    但是,如果由于某种原因,您不能或不愿意使用 Boost,则可以使用模板来执行此操作(诚然,这与 Boost 的解决方案非常相似):

    class FncPtr
    {
    public:
        virtual int call(float, char, char) = 0;
    };
    
    template <typename T>
    class ClassFncPtr : public FncPtr
    {
         int (T::*pt2Member)(float, char, char);
         T *inst;
    public:
         ClassFncPtr(T* who, int (T::*memfunc)(float,char,char))
             : inst(who), pt2Member(memfunc)
         {
         }
         int call(float a, char b, char c)
         {
             return (inst->*pt2Member)(a,b,c);
         }
    };
    
    template <typename T>
    FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char))
    {
        return new ClassFncPtr<T>(who,memfunc);
    }
    

    如果您愿意,您还可以继承 FncPtr 以便能够使用非类函数。

    【讨论】:

      【解决方案3】:

      您可以使用boost::function(和boost::bind)存储一段代码以供以后调用。

      class MyClass
      {
      public:
          void callThisFuncLater( boost::function< int (float, char, char) > callBack );
      };
      ...
      myObject.callThisFuncLater( boost::bind( &otherObject::method, &otherObject ) );
      

      【讨论】:

      • 我可能是错的,但&amp;otherObject&amp;otherObject::method 应该切换吗?
      • @Vortico 你是对的,我很抱歉。我将编辑我的帖子以更正它。
      【解决方案4】:

      我个人会选择不同的设计。仅仅是因为 C++ 中的成员函数指针不容易使用。就我个人而言,我会选择使用接口并从这些接口继承并沿这些接口进行解析。

      成员函数指针的一个问题是它们在不同的编译器上的实现方式不同。如果您使用 Borland/Embarcardero 编译器并希望将自己限制在此范围内,则可以使用 __closure 关键字,但很可能您不是,因此您必须使用其他编译器特定的实现,或者使用其中之一boost helper 类,如函数。

      但如果您发现在 C++ 中使用成员函数指针很有帮助,请重新考虑您的设计。

      【讨论】:

      • 闭包的标准替代方法是 lambda 函数,但这仍然不是成员函数的现实替代。
      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      • 2013-06-06
      相关资源
      最近更新 更多