1

クラスのファミリーのメンバー関数にアクセスするクラスを作成したいと考えています。さらに詳しく説明すると、次のように宣言されたクラス ControlChaos があります。

#define CALL_MEMBER_FN(object, ptrToMember) ((object)->*(ptrToMember))

typedef double (MultiMaps::*mapsGetPtr)();
typedef void (MultiMaps::*mapsSetPtr)(double para);

class ControlChaos
{
public:
    ControlChaos(MultiMaps* _map,
                 mat orbitPoints,
                 colvec initCond,
                 mapsGetPtr getPtr,
                 mapsSetPtr setPtr,
                 double deltaMax,
                 double epsilonNeighborhood,
                 int controlIterations,
                 int maxIterations);

/* Other stuff here. */
};

タイプ mapsGetPtr および mapsSetPtr などの保護されたメンバー変数を使用します。実装では、使用します

 CALL_MEMBER_FN(map,setPtr)(someParameter);

ControlChaosのコンストラクタで関数ポインタを使って指定した関数を呼び出す。アクセスしたいメンバー関数は、MultiMaps から派生したクラスのメンバーです。このコードは、単独で問題なくコンパイルされます。MultiMaps から派生したクラスのメンバー関数を指す関数ポインターを使用して ControlChaos オブジェクトをインスタンス化しようとすると、コンパイラーは、間違った引数の型を指定したと文句を言います。

さらに、この記事は、静的キャストが仕事をすることができることを暗示しているようですが、私はこれが真実であるとは知りませんでした.

これを解決する方法についてのアイデアはありますか?

4

1 に答える 1

1

typeのポインターからメンバーへのキャストをtypeにキャストするために必要なのは、static_cast だけです。次のスニペットを参照してください。Child::*Base::*

struct ChildOfMultiMap : MultiMap { 
   ...
};

...

void(ChildOfMultiMap::* child_mem_ptr)(double) = &ChildOfMultiMap::set;

mapsSetPtr ptr = static_cast<mapsSetPtr> (child_mem_ptr);

誤って のインスタンス(および関連する ではなく) でメンバーへのポインタを使用すると、これは危険である可能性があることに注意してください。BaseChild


これはどのような点で危険でしょうか?

以下のスニペットでは、前述とまったく同じアプローチを使用してChild::funcいますが、型のオブジェクトを呼び出すと、関数内の Baseの存在しないメンバーにアクセスしているため、未定義の動作Baseが発生します。

struct Base {
  /* ... */
};

struct Child : Base {

  void func () {
    this->x = 123;
  }

  int x;
};

int
main (int argc, char *argv[])
{
  typedef void (Base::*BaseFuncPtr) (); 

  BaseFuncPtr ptr_to_child_func = static_cast<BaseFuncPtr> (&Child::func);

  Base b;

  (b.*ptr_to_child_func) (); /* undefined-behavior */
}
于 2012-07-16T06:04:56.470 に答える