5

オブジェクトへのポインターと、既知の署名のメソッドへのポインターを保存したいと考えています。クラスがわかっている場合、このポインターのタイプは次のとおりです。

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

しかし、型がわからない場合、どうすればポインタを保存できますか?

私はこのようなことをしたい:

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

methodメソッドへのポインタを格納しmyObjectて後で呼び出すにはどうすればよいですか?

4

4 に答える 4

5

TR1 STL ライブラリ拡張機能 (gcc および Visual Studio 2008 以降で利用可能) にアクセスできる場合の最も簡単な方法は、後で呼び出すことができる呼び出しをラップするために std::function および std::bind を使用できます。この機能は、ブースト機能とブースト バインドでも利用できます。

#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_;
};
于 2011-10-16T19:47:59.027 に答える
4

言語または標準ライブラリに元々組み込まれているため、これを行う簡単な方法はありません(ただし、最近追加されました)。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必要に応じて、クラス以外の関数を使用できるようにサブクラス化することもできます。

于 2011-10-16T19:58:34.847 に答える
2

boost::function(and ) を使用boost::bindして、後で呼び出すコードを格納できます。

class MyClass
{
public:
    void callThisFuncLater( boost::function< int (float, char, char) > callBack );
};
...
myObject.callThisFuncLater( boost::bind( &otherObject::method, &otherObject ) );
于 2011-10-16T19:46:12.490 に答える
0

個人的には別のデザインを選びます。単純に、C++ のメンバー関数ポインターを操作するのは簡単ではないためです。個人的には、インターフェイスを使用してこれらを継承し、これらに沿って解析することを選択します。

メンバー関数ポインターの問題の 1 つは、コンパイラーによって実装が異なることです。Borland/Embarcardero コンパイラを使用していて、これに限定したい場合は、__closureキーワードを使用できますが、使用しない可能性が高いため、他のコンパイラ固有の実装を使用するか、boost ヘルパーのいずれかを使用する必要があります。関数のようなクラス。

ただし、C++ でメンバー関数ポインターを使用すると便利な場合は、設計を再検討してください。

于 2011-10-16T19:51:29.597 に答える