c++継承メカニズムが犯しやすいエラー

2183 ワード

オブジェクト向けの基本的な特徴の1つとして継承され、その使用率は極めて高い.ソフトウェアの基本機能を実現するためにも、再プログラムの再構築の過程でも、継承メカニズムを常に使用します.その用途が極めて広く、使用が簡単であるため、大衆プログラマーはその本当の内部実現メカニズムの探究が深くない.また,ほとんどの場合,継承の使い方は誤りである.次に例を用いて問題を説明する.
class Animal {
   public:
       Animal &operator=(const Animal &rhs);
       ...
};
class Animal1: public Animal {
   public:
       Animal1 &operator=(const Animal1 &rhs);
       ...
};
class Animal2: public Animal {
   public:
       Animal2 &operator=(const Animal2 &rhs);
       ...
};
上のコードは、ベースクラスとしてAnimal 1とAnimal 2が共通に継承する継承システムを簡単に定義するだけです.3つとも付与演算子を再ロードしました.これは問題の説明に十分だ.次のコードを考慮します.
Animal1 an1;
Animal2 an2;
Animal  *pAn1 = &an1;
Animal  *pAn2 = &an2;
...
*pAn1 = *pAn2;
の上のコードは十分簡単でしょう.問題が発生しました私たちの最後の行の目的はan 2をan 1に割り当てることです.もしあなたがこの目的でなければ、本文を迂回することができます!ポインタによるオブジェクトへの付与動作は,c++プログラマーにとって非常に一般的であるからである.しかし、実際の効果は、an 1のAnimal成分がan 2のAnimal成分と同じであり、an 1のAnimal 1コストは変わらないことである.
ここでこのような状況が発生した原因を述べる.継承システムの付与関数はリロードです.上書きや非表示ではなく(3つの違いに注意:);2.Animal*pAn 1=&an 1は、pAn 1がカバーする範囲を狭める効果を生み出すため、賦値操作を採用する場合、実際に呼び出される賦値関数のベースクラスの賦値関数です.この効果は、あなたのan 1オブジェクトが2つに似ていないか、元のan 1オブジェクトでも、あなたが期待するan 2オブジェクトでもありません.ただし、このような移花接木の効果まで、私はあなたにおめでとうございます.この使い方はとてもすばらしくて、あなたがc++の継承システムに対してすでに頂点に達したことを示しています.
しかし、ほとんどの人は移花接木の機能を実現していないが、どのようにしてすべての成分の付与効果を実現するのだろうか.
継承メカニズムが既に用いられている以上,虚関数から離れてはならない.割り当てオペレータ関数を虚関数として定義します.コードは次のとおりです.
class Animal {
   public:
       virtual Animal &operator=(const Animal &rhs);
       ...
};
class Animal1: public Animal {
   public:
       virtual Animal1 &operator=(const Animal1 &rhs);
 ...};class Animal2: public Animal { public: virtual Animal2 &operator=(const Animal2 &rhs);
...};
虚関数を使用すると、上述したすべての成分の付与効果を確実に解決することができます.これは、上述したリロードではなく、付与関数を上書きするため、実際のAnimal 1クラスの付与関数が呼び出されます.しかし、これは依然として問題をもたらします.次のコードです.
Animal1 an1;
Animal2 an2;//   Animal2  ,    Animal1  
Animal  *pAn1 = &an1;
Animal  *pAn2 = &an2;
...
*pAn1 = *pAn2;// Animal2     Animal1
このようにすると、異型変換が許可され、明らかに問題が発生します.どのように解決しますか?『More Effective c++』の条項34を参考にすることができます.