2

これは、このプラットフォームでの最初の質問です。不明な点や質問の仕方が適切でなかったら申し訳ありません。

以下のコードは、任意の C++11 コンパイラでコンパイルする必要があります。最小限に抑えてみました。このコードの意味は、この手順で失われる可能性がありますが、クラスと対応するメンバー関数のリストを保持して、それらすべてを同じパラメーターで呼び出すようにしようとしていることは明らかです。

#include <iostream>

class Base {
public:
  virtual void Call(int x) = 0;
};

template<class T> class Extended : public Base
{
  public:
  // Constructor.
  Extended(T* ptr, void (T::*memberFunction)(int)) : _ptr(ptr), _memberFunction(memberFunction) { }

  // Call function.
  void Call(int x) {
    (_ptr->*_memberFunction)(x);
  }

private:
  // Pointer to class T.
  T* _ptr;

  // Function pointer.
  void (T::*_memberFunction)(int);

};

class Test1 {
public:
  void Fun1(int x) { std::cout << "Hello " << x << std::endl; }
};

class Test2 {
public:
  void FunX(int x) { std::cout << (x * 2) << std::endl; }
};

class MyList {

 public:
 ~MyList() {
    for (auto it = _list.begin(); it != _list.end(); ++it) {
      delete (*it);
    }
  }

  template <class T> void Add(T* t, void (T::*memberFunction)(int)) {
    _list.push_back(new Extended<T>(t, memberFunction));
  }

  void CallAll(int g) {
    for (auto it = _list.begin(); it != _list.end(); ++it) {
        (*it)->Call(g);
    }
  }

private:
  std::list<Base*> _list;
};


int main() {
  MyList myList;
  Test1 test1;
  Test2 test2;
  myList.Add(&test1, &Test1::Fun1);
  myList.Add(&test2, &Test2::FunX);
  myList.CallAll(100);
}

これは完璧に機能します。私の問題は、リストからクラスとメンバー関数を削除する方法がわからないことです。さらに、同じクラスとメンバー関数が 2 回呼び出されることは望ましくありません。これは実質的に同じ問題です。Base 型の 2 つのクラスが等しいかどうかをチェックする必要があります。void ポインターを提供する仮想関数を提供できます。

virtual void* GetPtr() = 0;

しかし、それはクラスの同等性をチェックするだけです。このクラスの関数ポインターが等しいかどうかを確認する方法と、その方法がわかりません

template <class T> void MyList::Remove(T* t, void (T::*memberFunction)(int)) {

}

のように見える必要があります。

誰かが問題の解決策を知っていますか? それとも、このチェックはできませんか?

ジョー

4

1 に答える 1

0

仮想 isEqual メソッドを Base に追加します。

class Base {
public:
  virtual void Call(int x) = 0;
  virtual bool isEqual(const Base& other) = 0;
};

template<class T> class Extended : public Base
{

  public:
      virtual bool isEqual(const Base& other)
      {
         const Extended* otherPtr = dynamic_cast<const Extended*>(&other);
         return otherPtr != nullptr && otherPtr->_ptr == _ptr && otherPtr->_memberFunction == _memberFunction;
      }

};

仮想デストラクタを に追加しBaseます。そうしないと、メモリ リークが発生します。

また、メンバー変数の先頭で undescore を使用しないで_ptrください - 最後に使用する必要がある場合: ptr_. 先頭のアンダースコアの一部は、コンパイラ用に予約されています。

于 2012-10-13T13:08:21.520 に答える