2012-02-15 18 views
0

私は現在、C++プロジェクトに取り組んでおり、現在設計上の問題に直面しています。誰かが私に提案をくれれば感謝しています。基本的には、ベースクラスBaseと、以下のようにDerivedサブクラスを持っています。クラス派生クラスは、基本クラスが行うことができないことを行うことができます。dynamic_castにまともな代替手段がありますか

class Base 
{ 
public: 
    virtual bool IsCapableOfDoingA() {return false;} 
} 

class Derived: public Base 
{ 
public: 
    bool IsCapableOfDoingA() {return true;} 
    void DoA(); 
} 

私は、クラスBaseのポインタを持つ別の場所です。

void functionA(Base *pBase) 
{ 
    if (pBase && pBase->IsCapableOfDoingA()) 
    { 
     Derived *pDerived = static_cast<Derived*>(pBase); 
     pDerived->DoA(); 
    } 

} 
+1

動的な多型を最初に必要とする 'Base'と' Derived'では何をしていますか?コンテキストがなければ、この質問に答える方法はありません。 – ildjarn

+0

あなたの質問では、あなたは 'dynamic_cast'の代替案を尋ねますが、何が間違っていますか? – hvd

+0

これは、もう少しの文脈がなければ答えることは不可能です。しかし、あなたが推測したように、どのメンバ関数が存在するかを照会する必要がある場合は、設計を再考する必要があります。 –

答えて

4

一般的な方法は、基本クラスに関数を追加することです。

virtual void DoA() { throw std::runtime_error("Not implemented"); } 
+0

私はそれが普通だとは思わないでしょう。 –

+0

依存しています - 何もしないことが妥当で共通しているなら、 'virtual void DoA(){}'と書くだけです。問題には 'else'ブランチに' throw'が含まれていないことに注意してください。 – MSalters

2

デザインでは、DoAが正常終了コードを返すことはできますか? IsCapableOfDoingADoAと置き換えて、Baseのバージョンを単にfalse(または他の適切なエラーコード)に戻すことができます。 Aを実行できる子オブジェクトは、この機能を適切な実装でオーバーライドすることができます。

あなたは正しく、dynamic_castはデザインの匂いがします。より多くの文脈で、より良い答えを提供できるかもしれません。私が最初に考えたのは、できるだけ具体的にBaseを要求する場合は、Derived IS-A Baseを実際に確認することです。

+0

BaseはAを実行できないので、Baseはfalseを返しても構いません。しかし、BaseはAを実行することができないので、Baseにこのインタフェースを提供するのが本当に意味があるかどうかを考えています。 IIRCは、 "Effect C++"の本で議論されている設計上の問題です。著者は、鳥が飛ぶことができるかどうかを示しました。ですから、Birdクラスにはfly()を提供しないほうが良いですが、fly()メンバーメソッドを持つFlyableBirdのサブクラスを派生してください。 –

+0

うん、それは#Effective C++ _の第3版の#32です。スコットは提案をしています([Mark's answer](http://stackoverflow.com/a/9300547/46821)も絶対的な正解はありません)。 –

1

オブジェクトに適切な型がない場合、dynamic_castはNULLを返します(基本クラスが少なくとも1つの仮想メソッドを定義していると仮定します。通常、少なくとも基本クラスのデストラクタを仮想にする必要があります)。 PBASEはタイプが派生していない場合

void functionA(Base *pBase) 
{ 
    if (Derived *pDerived = dynamic_cast<Derived*>(pBase)) { 
     pDerived->DoA(); 
    }  
} 

、その後、pDerivedは0(偽)となりますので、if文の本体スキップされます:だから、あなたは、次のイディオムを使用することができます。

0

別の考えがあります。拡張された関数をインタフェースに分割し、インタフェースポインタを返すメソッドを持つことができます。

class InterfaceA 
{ 
public: 
    virtual ~InterfaceA() {} 
    virtual void DoA() = 0; 
}; 

class Base 
{ 
public: 
    virtual InterfaceA* GetAInterface() {return NULL;} 
}; 

class Derived: public Base, InterfaceA 
{ 
public: 
    InterfaceA* GetAInterface() {return this;} 
    void DoA(); 
}; 

void functionA(Base *pBase) 
{ 
    InterfaceA* pA = pBase ? pBase->GetAInterface() : NULL; 
    if (pA) 
     pA->DoA(); 
} 
+0

ありがとうございました。ソリューションにstatic_castは必要ありません。 –

関連する問題