仮想継承を行うと仮想関数の呼び出しはどうなるのでしょうか? 今回はそのあたりを考えてみようと思います。
では、今回の要点です。
では、いってみましょう。
今回は、前回のクラスに仮想関数 DispInfo を加えてみたいと思います。動作はそのクラスの情報を表示するというものです。
class CBuffer { ... 略 ... public: virtual void DispInfo() const = 0; }; ... 略 ... void CBufferRead::DispInfo() const { cout << "CBufferRead" << endl; } void CBufferWrite::DispInfo() const { cout << "CBufferWrite" << endl; } void CBufferRW::DispInfo() const { cout << "CBufferRW" << endl; } |
これはこれで構わないのですが、ここでひねくれてCBufferRW ではオーバーライドしないでおきます。つまりは、第52章で話した「CNinja と CMaster で GetString をオーバーライドしたとき、CJohnin ではどちらの GetString が呼ばれるのか」ということが仮想継承を使った場合どうなるかということです。
しかし、では試そうとコンパイルしてみると...何と BufferRW.cpp でコンパイルエラーが出てしまいます。どういうエラーが出たのか見てみましょう。
error C2250: 'CBufferRW' : 'CBufferRead::DispInfo'の継承があいまいです。 error C2250: 'CBufferRW' : 'CBufferWrite::DispInfo'の継承があいまいです。
関数を呼ぶ前から「あいまいだ」と文句を言っています。つまりは、仮想継承されたクラスにある仮想関数は、派生クラスを定義する時点であいまいさを除いておく必要があるということです。
むぅ。少し言葉が難しくなってしまいましたね。簡単にいってしまうと1つのクラスに沢山 DispInfo があったら困るということです。CBuffer は1つしかないので、扱う関数も1つである必要があるわけです。複数あったら処理の整合性をとるのが難しいですね。
CBufferRead の流儀で処理した結果を使って CBufferWrite で処理を行うと、処理が破綻してしまう場合があります。そういうことがないように、そういう処理は CBufferRW できちんと記述してやる必要があるわけです。
困ったことに、これ以上話すことがなくなってしまいました。ということで、短いですが今回はこれで終わりです。
では、今回の要点です。
今回で仮想継承については終わりです。あまり使いどころはないかもしれませんが、一応頭に置いておくと役に立つ日がくるかもしれませんね。それでは。
Last update was done on 2001.6.5
この講座の著作権はロベールが保有しています