marunomaruno-memo

marunomaruno-memo

[C++] ダイヤモンド継承

2011年11月03日 | C / C++
ダイヤモンド継承
================================================================================

※ mingw 3.4.2


ダイヤモンド継承で virtual 指定のときに、オーバーロードされた違うコンストラク
ターで初期化したときにどうなるの、ということで、試してみる。

クラス図としては、つぎのとおり
(U言語、http://objectclub.jp/technicaldoc/uml/u_lang/)。

    A <|------ B <|------- D
          +--- C <|---+

U 言語での多重継承の描き方はどうなんだろう。上記の表現は適当に記したが、本当はど
うかな。


□ diamond.cpp
---
#include <iostream>
using namespace std;

class A {
public:
    int a;
    A();
    A(int a);
};

class B: virtual public A {
public:
    B();
};

class C: virtual public A {
public:
    C(int a);
};

class D: public B, public C {
public:
    D(int a);
};

A::A() :
    a(-1) {
    cout << "A::A()" << endl;
}

A::A(int a) :
    a(a) {
    cout << "A::A(int a), a = " << a << endl;
}

B::B() :
    A() {
    cout << "B::B()" << endl;
}

C::C(int a) :
    A(a) {
    cout << "C::C(int a), a = " << a << endl;
}

D::D(int a) :
    B(), C(a) {
    cout << "D::D(int a), a = " << a << endl;
}

int main() {
    D d(123);
    cout << "d.a = " << d.a << endl;

    return 0;
}
---

□ 実行結果
---
A::A()
B::B()
C::C(int a), a = 123
D::D(int a), a = 123
d.a = -1
---



■ クラスD が B や C を指定する順番を逆にする


継承する順番を逆にすれば、d.a の値が 123 になるかと思ったが、そうはならず、-1 の
まま。
なぜだろう。


□ diamond.cpp
---
#include <iostream>
using namespace std;

class A {
public:
    int a;
    A();
    A(int a);
};

class B: virtual public A {
public:
    B();
};

class C: virtual public A {
public:
    C(int a);
};

//class D : public B, public C {
class D: public C, public B {
public:
    D(int a);
};

A::A() :
    a(-1) {
    cout << "A::A()" << endl;
}

A::A(int a) :
    a(a) {
    cout << "A::A(int a), a = " << a << endl;
}

B::B() :
    A() {
    cout << "B::B()" << endl;
}

C::C(int a) :
    A(a) {
    cout << "C::C(int a), a = " << a << endl;
}

//D::D(int a) :
//    B(), C(a) {
//    cout << "D::D(int a), a = " << a << endl;
//}

D::D(int a) :
    C(a), B() {
    cout << "D::D(int a), a = " << a << endl;
}

int main() {
    D d(123);
    cout << "d.a = " << d.a << endl;

    return 0;
}
---

□ 実行結果
---
A::A()
C::C(int a), a = 123
B::B()
D::D(int a), a = 123
d.a = -1
---


■ vartual を外す

vairtual を外すと、さすがにコンパイル・エラー。
    request for member `a' is ambiguous

□ diamond.cpp
---
#include <iostream>
using namespace std;

class A {
public:
    int a;
    A();
    A(int a);
};

class B: public A {
public:
    B();
};

class C: public A {
public:
    C(int a);
};

class D: public B, public C {
public:
    D(int a);
};

A::A() :
    a(-1) {
    cout << "A::A()" << endl;
}

A::A(int a) :
    a(a) {
    cout << "A::A(int a), a = " << a << endl;
}

B::B() :
    A() {
    cout << "B::B()" << endl;
}

C::C(int a) :
    A(a) {
    cout << "C::C(int a), a = " << a << endl;
}

D::D(int a) :
    B(), C(a) {
    cout << "D::D(int a), a = " << a << endl;
}

int main() {
    D d(123);
    cout << "d.a = " << d.a << endl;

    return 0;
}
---

□ ビルド結果
---
..\src\diamond.cpp: In function `int main()':
..\src\diamond.cpp:53: error: request for member `a' is ambiguous
..\src\diamond.cpp:6: error: candidates are: int A::a
..\src\diamond.cpp:6: error:                 int A::a
---




最新の画像もっと見る

コメントを投稿