4

クラスがあります

class BarBase {

};

メンバー関数へのポインターと同じクラスのオブジェクトへのポインターを格納する派生テンプレート クラス

template<typename TypeName> class Bar: public BarBase
{
    void ( TypeName::*action ) ( void );
    TypeName* object;
};

のインスタンスを作成Barし、それらへのポインタを別のクラスのベクトルに格納しますFoo

class Foo {
    private:
        vector<BarBase*> myBars;
    ...
};

今質問に。Fooにはテンプレート機能があります

template <typename TypeName>
void Foo::foo( TypeName* object , void ( TypeName::*action ) ( void ) )

この関数では、この関数のパラメーターと等しいmyBarsフィールドを持つ要素をどのように見つけることができますか? ご覧のとおり、のようなフィールドに直接アクセスすることはできません。これらのフィールドは のメンバーではない (メンバーになることもできない) からです。objectactionthis->myBars[i]->actionBarBase

EDIT 私は比較することができobjectます。virtual size_t getObject (){};toを追加して、 likeBarBaseでオーバーライドします。次に、2つを比較しますが、数値に変換する方法がわかりません...Barvirtual size_t getObject (){ return (size_t)this->object; };size_taction

4

2 に答える 2

2

最も簡単な解決策は、基本クラスをポリモーフィックにし、それを使用dynamic_castして期待される型を持っているかどうかを判断することです。

class BarBase {
public:
    virtual ~BarBase() {}  // virtual function required for polymorphism
};

Bar<TypeName>* bar = dynamic_cast<Bar<TypeName>*>(myBars[i]);
if (bar && bar->object == object && bar->action == action) {
    // it's a match
}

これにより、RTTI をサポートするためにいくらかのオーバーヘッドが追加されます。頭のてっぺんから、オーバーヘッドを追加せずにこれを行う明確に定義された方法は考えられません。

于 2012-08-29T12:58:10.157 に答える
1

Mikeバリアントを使用したくない場合は、このようなものを使用できます(私は彼のバリアントを好みます)。

class BarBase 
{
public:
   virtual ~BarBase() { }
   virtual void* getObject() { return 0; }
   virtual const char* getFunctionName() { return 0; }
};

template<typename T>
class Bar : public BarBase
{
public:
   Bar(T* obj, void (T::*func) (void)):object(obj), action(func)
   {
   }
   virtual void* getObject() { return object; }
   virtual const char* getFunctionName() { return typeid(action).name(); }
   T* object;
   void (T::*action)(void);
};

http://liveworkspace.org/code/d79e33d4597ee209645026b2100330f3

編集。

ごめん。typeid(&S::action).name()に等しい可能性があるため、問題の解ではありませんtypeid(&S::other_action).name()

また、ベクトル内のすべてのオブジェクトに対して使用するdynamic_castかどうかを指定できます。static_cast

class BarBase 
{
public:
   virtual ~BarBase() { }
   virtual void* getObject() const { return 0; }
};

template<typename T>
class Bar : public BarBase
{
public:
   Bar(T* obj, void (T::*func) (void)):object(obj), action(func)
   {
   }
   virtual void* getObject() const { return object; }
   T* object;
   void (T::*action)(void);
};

for (auto pos = objects.begin(); pos != objects.end(); ++pos)
{
      if ((*pos)->getObject() == &p)
      {
         auto bar = static_cast<Bar<S>*>(*pos);
         if (bar->action == act)
         {
            // right object founded.
         }
      }
   }

http://liveworkspace.org/code/87473a94411997914906c22ef0c31ace

于 2012-08-29T13:17:15.733 に答える