1

私が次のようなものを持っている場合

class Base1 {};

class Base2 {};

class Derived : public Base1, public Base2 {};

次に、Derived のオブジェクトを作成する際のコンストラクター呼び出しの順序は、

Base1
Base2 

つまり、表示される順序で

class Derived : public Base1, public Base2 {};

しかし、それをクラス Derived に変更すると: public Base1, virtual public Base2 {}; 次に、コンストラクター呼び出しの順序は次のようになります

Base2
Base1

なぜそうなのか理解できませんか?

別の単純な疑問: Base1 を仮想的に継承する意味と目的は何でしょうか。

4

3 に答える 3

4

それらは単なるルールです。構築される最も派生したクラスは、その非仮想直接ベースの初期化を開始する前に、まず階層内のすべての仮想ベース クラスを初期化します。

ルールは、標準 (ISO/IEC 14882:2011) のセクション 12.6.2 [class.base.init] / 10 に基づいています。

このアプローチの理論的根拠は、仮想ベースであるかどうかに関係なく、派生クラスの前にすべての基本クラスが初期化されることを保証することです。

于 2012-04-24T12:54:20.793 に答える
3

初期化の順序については、Charles はすでに適切に答えています。これらはルールです。最初に宣言の順序で仮想ベース、次に宣言の順序で非仮想ベース、次に宣言の順序でメンバー変数です。

仮想継承の意味は何ですか? これは、オブジェクトがその特定のベースから派生することを意味しますが、階層内で複数のサブオブジェクト (完全なタイプのベース) が同じベース タイプから事実上継承する場合、ベース サブオブジェクトは 1 つだけ存在します。完全なタイプで my を他のオブジェクトと共有したいのでvirtual、そこにあるキーワードを読むことができます。base

struct ubase {};
struct sbase {};
struct A : ubase, virtual sbase {};   // has a sbase subobject, but is willing to share..
struct B : ubase, virtual sbase {};   // ... but want to have my own ubase
struct C : A, B {};                   // only one sbase subobject, shared by A and B
                                      // ... but two ubase subobjects, A::ubase and B::ubase

2 番目の質問によると、いつ仮想継承を使用しますか? 型階層では、同じベースから複数回継承することになる可能性があり、設計では、それらのベース クラスの出現はすべて 1 つにすぎません。一般に、いくつかの特定のケースを除いて、仮想継承を使用することは非常にまれです。

于 2012-04-24T13:07:40.727 に答える
1

事実上の継承について。以下のような派生クラスがある場合に機能します

class A {};
class B : public virtual A {} ;
class C : public virtual A {} ;
class D : B, C { }  // this class has only one instance of A!

別名ダイヤモンド問題!

于 2012-04-24T12:59:50.193 に答える