Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
学ぶ ダイヤモンド継承 | イントロダクション
C++ OOP原則

bookダイヤモンド継承

メニューを表示するにはスワイプしてください

多重継承は、ダイヤモンド問題またはダイヤモンド継承として知られる状況を引き起こす可能性があり、これは多重継承をサポートするオブジェクト指向プログラミング言語における重要な課題です。

この問題は、サブクラスが2つ以上のclassesから継承し、それらが共通のスーパークラスから継承している場合に発生します。継承の構造がダイヤモンド型に見えることから、ダイヤモンドという用語が使われます。

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : public Base {}; class Derived2 : public Base {}; class Diamond : public Derived1, public Derived2 {};

ダイヤモンド継承における主な問題は、曖昧さが生じることです。DiamondDerived1Derived2の両方から継承し、それらがBaseから継承しているため、Baseオブジェクト内にDiamondが2つ存在することになります。これにより、曖昧さが発生します。

main.cpp

main.cpp

copy
12345678910111213141516
#include <iostream> class Base { public: void display() { std::cout << "Base display()" << std::endl; } }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

問題の解決方法

virtual キーワードはこの問題を回避するのに役立ちます。virtual キーワードを使用した仮想継承によって曖昧さを解消できます。Diamond が仮想的に継承される場合、C++ は異なる経路で複数回継承されてもスーパークラスのコピーが1つだけ存在するようにします。

main.cpp

main.cpp

copy
1234567
class Base {}; class Derived1 : virtual public Base {}; class Derived2 : virtual public Base {}; class Diamond : public Derived1, public Derived2 {};
Note
注記

前の例で発生した曖昧性の問題を、仮想継承を利用して解決する方法。

ダイヤモンド継承の実装

ダイヤモンド継承を効果的に実装するには、中間のclasses宣言でvirtualキーワードを使用します。継承階層のすべての経路で仮想継承を一貫して使用し、コンストラクタおよびデストラクタの呼び出し順序に注意します。

曖昧性の解消

多重継承の課題の一つは、同名メンバーが存在する場合の曖昧性への対応。

main.cpp

main.cpp

copy
12345678910111213141516171819
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.display(); // Ambiguity: Which display() method should be called? }

両方のスーパークラスに同じ名前のメンバーがある場合、サブクラスはどちらを使用するか分からないことがあります。このような曖昧さを解決するために、スコープ解決演算子::)を使用して、アクセスしたい基底クラスのメンバーを指定できます。例えば:

main.cpp

main.cpp

copy
1234567891011121314151617181920
#include <iostream> class Base {}; class Derived1 : public Base { public: void display() { std::cout << "Derived1 display()" << std::endl; } }; class Derived2 : public Base { public: void display() { std::cout << "Derived2 display()" << std::endl; } }; class Diamond : public Derived1, public Derived2 { }; int main() { Diamond obj; obj.Derived1::display(); obj.Derived2::display(); }
question mark

ダイヤモンド継承によって引き起こされる主な問題は何ですか?

正しい答えを選んでください

すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 1.  11

AIに質問する

expand

AIに質問する

ChatGPT

何でも質問するか、提案された質問の1つを試してチャットを始めてください

セクション 1.  11
some-alt