スポンサーリンク
前回「クラスはC++にデータ型を追加するための機能である」ということを説明した。
今回は、継承とは何か、を説明する。
くどいようだが、クラスは現実世界にあるモノの種類をデータ型として定義する機能である。継承はそれをさらに発展させ、
「○○は■■の一種である」という定義を、C++語で行うための機能なのである。
具体的な例を挙げると、日本語で「リンゴは果物の一種である」という定義を、C++言語で記述するための機能である。
「リンゴは果物の一種である」をC++語に翻訳すると、以下のようになる
class リンゴ : public 果物{...};
断っておきたいが、確かに継承した子クラスは親クラスのメンバ変数等をすべて持つことになる。だが、
継承は、似たようなクラスを量産するための機能ではない。
例えば
class Apple { unsigned char Color[3]; double weight; int price; };
が既に定義済みの時に、
class Orange { unsigned char Color[3]; double weight; int price; };
を作りたいとする。
もし、
class Orange : public Apple{ //継承したので、メンバ変数は全てAppleを引き継ぐ };
というコードを書いたら、それは
「このプログラムにおいて、オレンジはリンゴの一種であるとする」
と宣言したのと同じことなのだ。
例え既に定義されているクラスAppleと、メンバ変数も、メンバ関数も、全く同じクラスOrangeが必要になったとしても、「OrangeはAppleの一種である」という関係が成り立たないなら、継承を使ってはならない。
この例なら、普通は両方のクラスをFruitクラスからの継承とするだろう。以下のようになる。
※ただし、「Appleとほとんど同じ内容のクラスをもう一つ作るのは無駄に思えるので、Fruitを作って、AppleとOrangeはFruitを継承しましょう」ということを書いている解説書があるが、誤解を招く表現だと思っている。楽をするために継承を使ってはいけない。
class Fruit{ unsigned char Color[3]; double weight; int price; };
//リンゴというデータ型を定義。これは果物の一種である。 class Apple:public Fruit{ //果物の一種なので、パラメータの種類は果物から引き継ぐ }; //オレンジというデータ型を定義。これは果物の一種である。 class Orange:public Fruit{ //果物の一種なので、パラメータの種類は果物から引き継ぐ };
だが、それすらできない場合もある。
class すっぽん : public 月{ ... }
日本語には「月とすっぽん」ということわざがある。意味は、
似たところもあるが、比較にならないほどの違いがある
である。月はすっぽんの一種ではないし、その逆でもない。そしてこの両者は方や生き物、方や星である。種類としての共通点がない。
そしてこれは「ほかのプログラマから、オレンジはリンゴの一種という意図をもって書いたと解釈され、馬鹿にされる」という次元の話をしているのではない。
class Orange : public Apple は、OrangeはAppleの一種である、という定義のC++語訳であるから、C++のコンパイラがそのように解釈してしまうのが困る点なのである。C++が意味を勘違いすると、後でとんでもないバグを引き起こす可能性がある。正確には、プログラマのミスを検出してくれないのである。
続く...