間接的に同じクラスを複数継承させる場合、メンバ変数はどうなるのでしょうか? 今回はそういう話です。
では、今回の要点です。
では、いってみましょう。
先ずは、前回の多重継承をもうちょっとよく考えてみます。
では、前回の継承図をもう一度見てみましょう。
CFirstClass | CFirstClass | |
---|---|---|
| | | | |
CMaster | CNinja | |
| | | | |
CJohnin |
このように、CFirstClass クラスは間接的に2つ継承されています。
この継承関係は多少複雑ですが、
CMaster | CNinja | |
---|---|---|
| | | | |
CJohnin |
に毛の生えた程度と考えればそう複雑というわけでもありません。
CNinja は CFirstClass を継承しています。つまり、CNinja は CFirstClass を拡張したクラスです。これは CMaster も同じです。これら CNinja と CMaster は CFirstClass を継承していて、確かに両方とも CFirstClass への参照へオブジェクトを渡せますが、これらは基本的に独立したクラスです。
ここでいう「独立した」という意味は、CJohnin で2つを継承しても、CNinja の CFirstClass と CMaster の CFirstClass は別物であるという意味です。CNinja 経由で CFirstClass のメンバを呼んでも、CMaster の CFirstClass には影響を与えません。
これは CFirstClass にメンバ変数を持たせてやるとよく分かると思います。
CFirstClass | CFirstClass | |
---|---|---|
a : 0 | a : 0 | |
| | | | |
CMaster | CNinja | |
| | | | |
CJohnin |
CNinja 経由で CFirstClass のメンバ変数 a を1に変えてみると、
CFirstClass | CFirstClass | |
---|---|---|
a : 0 | a : 1 | |
| | | | |
CMaster | CNinja | |
| | | | |
CJohnin |
と、こうなります。
このように、CJohnin において2つの CFirstClass は独立して存在しています。こういうイメージでしょうか?
|
---|
しかし、継承の方法をいろいろ考えた結果、次のような継承を行いたい場合が出てくるかもしれません。
CFirstClass | ||
---|---|---|
| | | | |
CMaster | CNinja | |
| | | | |
CJohnin |
CFirstClass が1つになっています。つまり、CNinja 経由でも CMaster 経由でも、同じ CFirstClass を扱うようになるわけです。
これがどういうことかは、やはりメンバ変数を考えると分かりやすいと思います。
CFirstClass | ||
---|---|---|
a : 0 | ||
| | | | |
CMaster | CNinja | |
| | | | |
CJohnin |
このように、CFirstClass が1つしかないので、a は1つしかありません。先ず、CMaster 経由で a の値を調べると、もちろん0となります。ここで CNinja 経由で a を変えて...
CFirstClass | ||
---|---|---|
a : 1 | ||
| | ↑ | |
CMaster | CNinja | |
| | ↑ | |
CJohnin |
もう一度CMaster 経由で a の値を調べると...
CFirstClass | ||
---|---|---|
a : 1 | ||
↓ | | | |
CMaster | CNinja | |
↓ | | | |
CJohnin |
今度は1になっているわけです。
では、こういった継承はどうやったらできるようになるのでしょうか? 前回までの方法ではこういった継承にはならないので、もうちょっと別の方法があることは分かると思います。
実は、こういった継承は仮想継承という機構を使って行うことができます。仮想継承されたクラス同士は、同時に複数継承されなくなります。
つまりは、CNinja で CFirstClass を継承するときに仮想継承にして、CMaster で CFirstClass を継承するときに仮想継承にしておけば、CJohnin で CNinja と CMaster を継承しても CFirstClass は1つになるのです。
仮想継承するには、やはり virtual キーワードを使います。
class CNinja : virtual public CFirstClass { ... };
これで仮想継承できます。
一度に沢山話しても頭に入らないと思うので、今回は仮想継承の基本概念について話すだけにとどめ、実際のプログラムについては次回に話したいと思います。
では、今回の要点です。
仮想継承は、お馴染みの iostream.h にある iostream というクラスで使われています。ios というクラスを仮想継承して istream と ostream を作り、それらを継承して iostream を作っています。仮想継承が実際にどう使われているかの例としてあげておきます。
では、次回まで。
Last update was done on 2001.5.19
この講座の著作権はロベールが保有しています