多重継承
次の3つのクラスがあるものとします。C は、2つの基底クラス A, B からの派生クラスです。
その結果、C は、2つの基底クラスの資産を継承することになります。このような継承の形を、多重継承と呼びます。
【クラス A】
コンストラクタ … 「 A 」 を表示
デストラクタ … 「~A 」 を表示
データメンバ x = 1
メンバ関数 get_x() … x の値を返却
【クラス B】
コンストラクタ … 「 B 」 を表示
デストラクタ … 「~B 」 を表示
データメンバ x = 1
メンバ関数 get_x() … x の値を返却
【クラス C】 基底クラス A, B を多重継承
コンストラクタ … 「 C 」 を表示
デストラクタ … 「~C 」 を表示
データメンバ x = 1
メンバ関数 get_x() … x の値を返却
次のプログラムの結果から、 コンストラクタが呼び出される順序 と、 デストラクタが呼び出される順序 が確認できます。
また、クラス C は、
基底クラス部分オブジェクト A のデータメンバ x
基底クラス部分オブジェクト B のデータメンバ x
派生クラス C のデータメンバ x
の3つの x を保持することになります。
これらに、get_x関数でアクセスする際には、
c.A::get_x();
c.B::get_x();
c.get_x();
のように、 明確な指定が必要 になります。
// ---------------------------
#include <iostream>
using namespace std;
class A {
protected:
int x;
public:
A() { cout << "A" << '\n'; x = 1; }
~A() { cout << "~A" << '\n'; }
int get_x() const { return x; }
};
class B {
protected:
int x;
public:
B() { cout << "B" << '\n'; x = 2; }
~B() { cout << "~B" << '\n'; }
int get_x() const { return x; }
};
class C : public A, public B {
protected:
int x;
public:
C() { cout << "C" << '\n'; x = 3; }
~C() { cout << "~C" << '\n'; }
int get_x() const { return x; }
};
int main() {
A a;
cout << "------\n";
B b;
cout << "------\n";
C c;
cout << "------\n";
cout << c.A::get_x() << ' '
<< c.B::get_x() << ' '
<< c.get_x() << '\n';
cout << "------\n";
}
// ------------------------------------
新版明解C++中級編 p.244 演習7-1
以下のクラス群のクラス階層図を描き、クラス Z型のオブジェクトを初期化する際の基底クラス部分オブジェクトの初期化の順序を示せ。
class A{ /* ・・・・・・ */ };
class B{ /* ・・・・・・ */ };
class X : A, B{ /* ・・・・・・ */ };
class Y : B, A{ /* ・・・・・・ */ };
class Z : X, Y{ /* ・・・・・・ */ };
※アクセス指定子 public, protected, private が記述されていない場合は、private派生と解釈されます。
クラス階層図
Z型のオブジェクトを初期化する際の規定クラス部分オブジェクトの初期化の順序は、次のプログラムの出力結果の2本の "
"線の間で確認できます。
// ---------------------------
#include <iostream>
class A {
public:
A() { std::cout << "A" << '\n'; }
};
class B {
public:
B() { std::cout << "B" << '\n'; }
};
class X : A, B {
public:
X() { std::cout << "X" << '\n'; }
};
class Y : B, A {
public:
Y() { std::cout << "Y" << '\n'; }
};
class Z : X, Y {
public:
Z() { std::cout << "Z" << '\n'; }
};
int main() {
A a;
B b;
X x;
Y y;
std::cout << "\nZ型のオブジェクトを初期化"
"する際の \n規定クラス部分オ"
"ブジェクトの初期化の順序 \n"
"↓\n------\n";
Z z;
std::cout << "------\n";
}
// ------------------------------------