6

仮想基本クラス(通常は菱形継承問題を解決するために使用される)の使用法を説明する多くのチュートリアルでは、多くの場合、この構造の設計に類似したコードがあります。

class Animal
{
public:
    Animal()
    {
        cout << "Creating Animal\n";
    }
};

///////////////////////////

class FourLegs : virtual public Animal
{
public:
    FourLegs()
    {
        cout << "Creating FourLegs\n";
    }
};

///////////////////////////

class Mammal : virtual public Animal
{
public:
    Mammal()
    {
        cout << "Creating Mammal\n";
    }
};

///////////////////////////

class Fox : public FourLegs, public Mammal
{
public:
    Fox()
    {
        cout << "Creating Fox\n";
    }
};

Foxのインスタンスを作成すると、期待どおりの出力が得られます。作成された動物は1つだけです。

Creating Animal
Creating FourLegs
Creating Mammal
Creating Fox

ご覧のとおり、2つのTier2クラスが仮想的に継承しています。現在、1つのティア2クラスのみが仮想的に継承され、もう1つはパブリックにのみ継承される場合、興味深い出力が発生する可能性があります。たとえば、FourLegsがパブリックに継承され、Mammalが仮想パブリックに継承される場合、これは次の出力になります。

Creating Animal
Creating Animal
Creating FourLegs
Creating Mammal
Creating Fox

これは奇妙で、疑問を投げかけます。継承ツリーのどこかに仮想継承を含むクラスを作成する完全なプロセスは何ですか?

一方、I FourLegsが仮想パブリックを継承し、Mammalがパブリックを継承している場合、出力は通常どおりです(仮想パブリックを継承していないかのように)。

Creating Animal
Creating FourLegs
Creating Animal
Creating Mammal
Creating Fox
4

2 に答える 2

3

標準から直接、12.6.2 / 10 [class.base.init]

非委任コンストラクターでは、初期化は次の順序で進行します。

  • まず、最も派生したクラス(1.8)のコンストラクターの場合のみ、仮想基本クラスは、基本クラスの有向非巡回グラフの深さ優先の左から右へのトラバースに表示される順序で初期化されます。 to-right」は、派生クラスbase-specifier-list内の基本クラスの出現順序です。

  • 次に、直接基本クラスは、base-specifier-listに表示される宣言の順序で初期化されます( mem-initializersの順序に関係なく)。

  • 次に、非静的データメンバーは、クラス定義で宣言された順序で初期化されます(ここでも、mem-initializersの順序に関係なく)。

  • 最後に、コンストラクター本体の複合ステートメントが実行されます。

[:初期化の逆の順序でベースおよびメンバーのサブオブジェクトが確実に破棄されるように、宣言の順序が必須です。—エンドノート]

最初の箇条書きは、仮想継承を含むクラスで初期化がどのように行われるかを説明しています。

于 2012-06-24T21:41:06.637 に答える
0

予期しない出力は予期しないものではありません。これは、からFourLegs派生しAnimal、のコンストラクターを呼び出す必要があるために発生しAnimalます。virtualこの問題を防ぐには、すべての中間クラスを-化するという確立された規則が必要です。あなたの例の根本的な問題は、の概念が継承FourLegsされた特性として使用されているのに対し、それは構成的な特性として使用されるべきであるということです。つまり、哺乳類/動物が内部に持っている脚の数、または(特定の要件に応じて)派生クラスがフィールドを継承する脚の数を表すフィールドがあります。MammalAnimal

于 2012-06-24T21:45:17.740 に答える