2016-05-11 9 views
1

は、私はクラスの階層があります送信者オブジェクトの種類を知る最も良い方法は何ですか?

class A 
{ 
}; 

class B : public A 
{ 
}; 

class C : public B 
{ 
}; 

class D : public A 
{ 
}; 

を、私は通知を行い、いくつかの機能を、持っている:

void notify(A* sender, const NotificationType notification) 
{ 
} 

を私の問題は、送信者のオブジェクトの正確な型を見つける方法です。私はこの問題を解決するエレガントな方法を探したい。私はこれらの目的のためにダイナミックキャストを使用するのは嫌です。

enum ClassType 
{ 
    CLASS_A, 
    CLASS_B, 
    CLASS_C, 
    CLASS_D 
}; 

と仮想メソッドを定義:

virtual ClassType get_type(void) const; 

しかし、このアプローチは悪い拡張性を持っている可能性のある方法は次のようにクラス内で列挙型を定義することです。この情報をNotificationTypeに保持する別の方法ですが、スケーラビリティも悪いです。

P.S.

私は、同様のコードを使用したい:あなたはあなたの階層を永続化するタイプを知っているしたい場合

void notify(A* sender, const NotificationType notification) 
{ 
    if (sender is object of A) 
     new GuiA(); 
    else if (sender is object of B) 
     new GuiB(); 
    else if (sender is object of C) 
     new GuiC(); 
    else 
     new GuiD(); 
} 
+9

「送信者オブジェクトの正確な種類を調べる方法」知っておく必要がある場合は、間違っていると思います。 –

+2

「送信者」の具体的な種類を知る必要がある理由を説明できますか? – hansmaad

+4

多態的に行動するようにアプリケーションを設計し、具体的な型を知る必要性を感じるのは独特のようです。 –

答えて

2

を、ブーストを使用するconside :: TypeIndex(http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html)私は、同様のコードを使用します。

異なるタイプの異なるタイプを異なる方法で処理したい場合は、タイプ識別子のVisitor instituteを使用するか、仮想関数を使用して抽象的なインターフェイスを作成してニーズに合わせることにします。

EDITED

あなたの目標は、種類ごとに異なるUIオブジェクトを作成することです。あなたは、あなたの目標を達成するために、次のモデルを使用することができます。

class UIObject {...}; 
class UIObjectFactory {...}; 
class A { 
public: 
    virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0; 
}; 

void OnNotify(A* sender) { 
    auto ptr = sender->Create(GetUIFactory()); 
    ... 
} 
2

senderの具体的な種類に基づいて、一致するGUIオブジェクトを作成するには、Aにファクトリメソッドのいくつかの種類に工場を渡すことができます。

class A 
{ 
public: 
    virtual Agui* createGui(GuiFactory& fac) = 0; 
}; 

class GuiFactory 
{ 
public: 
    virtual Agui* forB(B&) = 0; 
    virtual Agui* forC(B&) = 0; 
    virtual Agui* forD(D&) = 0; 
}; 

class B : public A 
{ 
public: 
    Agui* createGui(GuiFactory& fac) 
    { 
     return fac.forB(*this); 
    } 
}; 

void notify(A* sender, const NotificationType notification) 
{ 
    // Use A interface... 
    // Get the concrete GuiFactory from somewhere, and use it 
    auto gui = sender->createGui(win32GuiFactory); 
} 
0

と仮想メソッドの定義:

virtual ClassType get_type(void) const; 

これを達成し、スケーラビリティの問題を取り除くための最も簡単な方法は、各クラスABであなたのget_type()メンバ関数を実装することである、C 、...このように:

typedef uintptr_t ClassType; 
virtual ClassType get_type() const 
{ 
    static int dummy; 
    return reinterpret_cast<ClassType>(&dummy); 
} 

静的変数dummyは、このメンバ関数を追加する各クラスに対して作成されるため、戻り値によってクラスが一意に識別されます。

関連する問題