2012-01-31 14 views
0

私はダイヤモンドの恐怖パターンを形成する必要があります。しかし、スタックオーバーフローメイトからのコメントには、仮想基底クラスが純粋な抽象クラスであれば、ダイヤモンドパターンはそれほど懸念されていないという意見が出てきました。誰かがなぜこれについて拡張してくださいそれはそうですか?C++ - 多重継承

答えて

5

C++での複数の継承は、強力ではあるが扱いにくいツールであり、慎重に使用しないと問題につながることがよくあります。

次の記事では、仮想継承を使用してプログラマーが実行する一般的な問題のいくつかを解決する方法を説明します。

Solving the Diamond Problem with Virtual Inheritance

次のようにダイモンドを実装しよう:記事は非常に良い説明を与える

class storable 
{ 
     public: 
     storable(const char*); 
     virtual void read()=0; //this becomes pure virtual making storable an abstract 
     virtual void write(); //class 
     virtual ~storable(); 
     private: 
     .... 
} 

class transmitter: public virtual storable 
{ 
     public: 
     void write() 
     { 
       read(); 
       .... 
     } 
} 

class receiver: public virtual storable 
{ 
     public: 
     void read(); 
} 

class radio: public transmitter, public receiver 
{ 
     public: 
     ... 
} 

int main() 
{ 
     radio *rad = new radio(); 
     receiver *r1 = rad; 
     transmitter *r2 =rad; 

     rad->write(); 
     r1->write(); 
     r2->write(); 
     return 1; 
} 
1

仮想継承について知っているかわからないかわかりません。ダイヤモンドパターン。単純な答えは、継承が仮想ではない場合(ダイヤモンドの根底から)、ダイヤモンドの代わりにVがあり、完全型には2つのの基本クラスの独立したコピーが含まれています。仮想継承は基本的にコンパイラに、継承関係でその基本を仮想として記述する中間型の数にかかわらず、完全型(ほとんどの派生)で基本のコピーを1つだけ必要としていることを伝えています。

もちろん

、アプローチは、カプセル化が何らかの形で破損しているという事実の例の場合と同様に、独自の問題が表示されます(派生型しなければならないの継承関係のノウハウを呼び出すために、彼らの仮想ベースに対して塩基でありますコンストラクタ)、仮想ベースサブオブジェクトに対する操作は、いくぶん複雑で高価になります。

+0

通常、仮想ベースは抽象クラスであり、データメンバは存在しないため、(マシン生成の)デフォルトのコンストラクタのみが使用されます。まれな例外があるかもしれませんが、それ以外の場合は、派生クラスの作成者が仮想継承を意識する必要はありません。 –

+0

@JamesKanze:正直言って、私はいくつかの時間に使用されている仮想ベースを見ているだけで、あなたが言うもの(純粋な抽象クラス)に従うものもあればそうでないものもありました。ここでも仮想基底クラスの経験は非常に限られています。 –

+0

私はそれがアプリケーションに大きく依存すると思います。私は広範囲にそれらを使用するいくつかのアプリケーションを見てきました。他のものははるかに少ないか、まったくない。 (私は広範囲に悪用するアプリケーションも見てきました。)一般に、それらがうまく使用された場所では、データのある仮想ベースはまれでした(そして、ほとんどがマシン生成コードです)。 –