0

私はメンバー関数へのポインターに不慣れであり、それらの長所と短所を知りたいです。

具体的には、次のことを考慮してください。

#include <iostream>
#include <list>

using namespace std;

class VariableContainer;

class Variable
{
public:
  Variable (int v) : value (v), cb_pointer (0) {}
  ~Variable () {}

  void SetCallback (void (VariableContainer::*cb)(int)) {
    cb_pointer = cb;
  }
  void FireCallback (void) {
    /* I need a reference to a VariableContainer object! */
  }

private:
  int value;
  void (VariableContainer::*cb_pointer) (int);
};

class VariableContainer
{
public:
  VariableContainer () {}
  ~VariableContainer () {}

  void AddVar (Variable &v) {
    v.SetCallback (&VariableContainer::Callback);
  }
  void Callback (int v) { cout << v << endl; }
};

int main ()
{
  Variable v (1);
  VariableContainer vc;

  vc.AddVar (v);
  v.FireCallback();

  return 0;
}

コメントで述べられているように、コールバック(FireCallback)をトリガーするには、既存のVariableContainerオブジェクトへの参照が必要です。これは、の追加の引数として提供する必要がありますVariableContainer::AddVar (...)。今:

  1. メンバー関数へのポインターを使用する必要がありますか?または、直接呼び出す必要がありますかCallback (...)(オブジェクトへのポインターがあるためVariableContainer)?
  2. 各ソリューションの長所と短所は何ですか?

TIA、ジル

4

2 に答える 2

2

将来の変化に応じて、次のことを決定できます。

  • 他の関数は変数の FireCallback によって呼び出されます => mf へのポインターが役立つ場合がありますが、他のメカニズムはより c++ っぽいです
  • 「Callback」関数のみが呼び出されます =>arg->CallBack()直接呼び出すことに固執します。

この問題の解決策として考えられるのは、インターフェース層を使用することです。これは、オブザーバー パターンの実装にすぎません。これはもう少しオブジェクト指向なので冗長ですが、構文はずっと簡単です。

class Observer {
public:
    virtual ~Observer(){};
    virtual void callback( int v ) = 0;
};

// actual implementation
class MyCallbackObserver : public Observer {
    virtual void callback( int v ) { std::cout << v << std::endl; }
    void some_other_method( int v ) { std::cout << "other " << v ; }
};

Variableクラスには、オブザーバーでいっぱいのコンテナーがあります。

class Variable {
public:
   std::vector<Observer*> observers; // warning: encapsulation omitted
   void FireCallback(){
      // assuming C++ 0x
      for( auto it : observers ) {
        (*it)->Callback( value );
      }
   }

同じオブジェクトで他の関数を呼び出す必要がある場合は、ラッパーを導入できます。

class OtherCaller: public Observer {
 public:
     MyObserver* obs;
     virtual void callback( int v ) { obs->some_other_method( v ); }
}

コレクションに追加します。

Variable var;
MyObserver m;
OtherCaller mo;
mo.obs = &m;

var.observers.push_back(&m);
var.observers.push_back(&mo);

var.FireCallback();
于 2010-07-14T14:10:46.103 に答える
1

ここでのニーズによって異なります。

コールバック関数が 1 つしかなく、その名前が常にわかっている場合は、それを直接呼び出すこともできます。よりシンプルで理解しやすく、余分な変数を必要としません。

構成に応じていくつかのコールバックのいずれかを呼び出す機能が必要な場合、メンバー関数ポインターが役立ちます。コールバック メンバー関数ポインターを呼び出したい実際のコールバックに設定し、それを使用して実行するコールバックを選択します。 .

于 2010-07-14T13:28:03.190 に答える