-5
#include<iostream>
using namespace std;
class Person {
   // Data members of person
public:
    Person(int x)  { cout << "Person::Person(int ) called" << endl;   }
};

class Faculty : public Person {
   // data members of Faculty
public:
    Faculty(int x):Person(x)   {
       cout<<"Faculty::Faculty(int ) called"<< endl;
    }
};

class Student : public Person {
   // data members of Student
public:
    Student(int x):Person(x) {
        cout<<"Student::Student(int ) called"<< endl;
    }
};

class TA : public Faculty, public Student  {
public:
    TA(int x):Student(x), Faculty(x)   {
        cout<<"TA::TA(int ) called"<< endl;
    }
};

int main()  {
    TA ta1(30);
}

O / p:

Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called

上記のひし形では、2つの親クラスが仮想キーワードを持つ祖父母から継承されているため、Personクラスのコンストラクターは1回だけ呼び出されます。しかし、なぜ祖父母のデフォルトコンストラクターがここで呼び出されたのですか。誰かが正確な理由を教えてもらえますか

4

3 に答える 3

2

TAは であるため、のコンストラクターが呼び出されることPersonについて予期しないことは何もありません。主張したように仮想継承を使用した場合、クラスには単一のサブオブジェクトが含まれるため、コンストラクターが一度呼び出されるという事実が予想されます。仮想継承を使用していない場合、には 2 つのサブオブジェクトがあり、2 つのコンストラクター呼び出しが予想されます。PersonTAPersonTAPersonPerson

于 2012-09-23T06:30:54.310 に答える
1

ダイヤモンド構成には、仮想基本クラスが必要であるか、オブジェクト表現で重複する必要があります。

class A
{
}

class B : virtual public A
{
};

class C : virtual public A
{
}

class D: public B, public C
{
}

これにより、A の単一の表現のみが型 D の最終オブジェクトになり、すべてで共有されるようになります。

これを介してコンストラクターパラメーターを渡す方法は、質問者への演習として残します。直感的ではありませんが、Google +「仮想基本クラス」は啓発以上のものになります。

于 2012-09-23T06:34:02.440 に答える
0

C++ Faqはあなたの質問にうまく答えます:

[25.12] 仮想継承を使用するクラスから継承する際に知っておく必要がある特別な考慮事項は何ですか?

最も派生したクラスの ctor の初期化リストは、仮想基本クラスの ctor を直接呼び出します。

仮想基本クラスのサブオブジェクトはインスタンス内で 1 回しか発生しないため、仮想基本クラスのコンストラクターとデストラクターがインスタンスごとに 1 回だけ呼び出されるようにするための特別な規則があります。C++ の規則では、仮想基底クラスはすべての非仮想基底クラスの前に構築されると規定されています。プログラマーとして知っておく必要があるのは、クラスの継承階層内の任意の場所にある仮想基本クラスのコンストラクターは、「最も派生した」クラスのコンストラクターによって呼び出されるということです。

実際には、これは、仮想基本クラスを持つ具象クラスを作成するときに、仮想基本クラスのコンストラクターを呼び出すために必要なパラメーターを渡す準備ができている必要があることを意味します。そしてもちろん、クラスの祖先のどこかに複数の仮想基底クラスがある場合は、それらのすべてのコンストラクターを呼び出す準備ができている必要があります。これは、最も派生したクラスのコンストラクターが、他の方法で考えるよりも多くのパラメーターを必要とすることを意味する場合があります。

ただし、仮想基本クラスの作成者が以前の FAQ のガイドラインに従っている場合、初期化するデータがないため、仮想基本クラスのコンストラクターはおそらくパラメーターを取りません。これは、(幸いなことに!) 仮想基本クラスから最終的に継承する具象クラスの作成者が、仮想基本クラスの ctor に渡す追加のパラメーターについて心配する必要がないことを意味します。

于 2012-09-23T06:35:38.283 に答える