「C++言語」の「多重継承」の仕組みを学んでみよう!
クラスに「継承」関係を作る際に、「複数の親クラス」を「継承」できる仕組みのことを「多重継承」と言います。
「複数」の親クラスを持つことで発生する問題や、どのように多重的な継承関係を作るのかを学んでいきたいと思います。
学習速度が早すぎて、まだ全然これまでに学んだ内容も「うる覚え」な状態ですが、少しずつ「C++言語」のさまざまな機能を使えるようになっていきたいと思います。
「多重継承」の仕組みと作り方
一つのクラスを親として「継承関係」を作る方法について学んでいきましたが、今回は、2つ以上のクラスを「親」に持つクラスの作り方を勉強していきたいと思います。
まず、「親」となる基底クラスを2つ作り「派生クラス」となるクラスを1つ作っていきます。
「Parent1」クラスのヘッダーファイルは、
#ifndef ___CLASS_Parent1 #define ___CLASS_Parent1 #include "Parent1.h" class Parent1 { public: void test(); }; #endif
のように作成し、「実装ファイル」は、
#include#include "Parent1.h" using namespace std; void Parent1::test(){ cout << "call Parent1 test method." << endl; }
「Parent2」クラスのヘッダーファイルは、
#ifndef ___CLASS_Parent2 #define ___CLASS_Parent2 #include "Parent2.h" class Parent2 { public: void test2(); }; #endif
のように作成し、「実装ファイル」は、
#include#include "Parent2.h" using namespace std; void Parent2::test2(){ cout << "call Parent2 test method." << endl; }
のように作りました。といっても、メンバ関数が一つだけのめちゃシンプルな「基底クラス」です。
この2つの基底クラスを継承する「Child」クラスの「ヘッダーファイル」は、
#ifndef ___CLASS_Child #define ___CLASS_Child #include "Parent1.h" #include "Parent2.h" #include "Child.h" class Child : public Parent1, public Parent2 { public: void test3(); }; #endif
のようになり、「実装ファイル」は、
#include#include "Child.h" using namespace std; void Child::test3(){ cout << "call Child test method." << endl; }
のようになります。
「ヘッダーファイル」では、
class 派生クラス名 : 継承方法 基底クラス1, 継承方法 基底クラス2 { }
のようにカンマ区切りで複数の基底クラスを書くと「多重継承」することができます。
「Child」クラスは、基底クラスの持っているメンバ関数を使うことができるため、
#include#include "Parent1.h" #include "Parent2.h" #include "Child.h" using namespace std; int main() { Child ch; ch.test(); ch.test2(); ch.test3(); return 0; }
のように、「main」関数を作って実行すると、
call Parent1 test method. call Parent2 test method. call Child test method.
のように表示され、2つの基底クラスのメンバ関数が実行できていることがわかります。
ただ、「基底クラス」にもし「同じ名前のメンバ関数」が作られていたらどうなるのか気になったので、調べてみました。
「Parent2」クラスの「test2」メンバ関数を、「Parent1」クラスと同じ「test」メンバ関数に名前を変更し、「test」関数を「main」関数で実行しました。
すると、
error: request for member 'test' is ambiguous
のように、「main」関数のコンパイル時にエラーメッセージが出ました。
なので、自分以外の人が作った「基底クラス」を多重継承したら、こういうことがたくさん起こるような気がします。
「基底クラス」に重複した名前のメンバ関数がある場合は、
基底クラス名::メンバ関数名();
のようにプログラムを書くと、エラーが出ず、指定した基底クラスのメンバ関数を実行することができるようになります。
「多重継承」って便利なのか、使わない方がいいのか悩みますね(^^;)
どのような機能なのかは理解できたので、もし利用できるケースがあれば使ってみたいと思います。