8

次のコードがあります。

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
#define MNAME 30
class Person {
public:
    char name[MNAME + 1];
};
class Student : public Person {
};
class Staff : public Person {
};
class Faculty : public Student, public Staff {
};

int _tmain(int argc, _TCHAR* argv[])
{
    Faculty faculty;
    cout << "Address of faculty.Person::name: " << &faculty.Person::name << endl;
    cout << "Address of faculty.Student::name: " << &faculty.Student::name << endl;
    cout << "Address of faculty.Staff::name: " << &faculty.Staff::name << endl;

    getch();
    return 0;
}

プログラムを実行すると、次の結果が得られます。

Address of faculty.Person::name: 0012FF20 // **Line 1**
Address of faculty.Student::name: 0012FF20 // **Line 2**
Address of faculty.Staff::name: 0012FF3F // **Line 3**

理解できません。Student と Staff の両方が Person から名前を継承しているのに、 との住所がLine 1Line 2異なるのはなぜですか?Line 3

4

7 に答える 7

13

この方法で多重継承を行うと、祖父母クラスのコピーが 2 つ取得されます。これは、これを実行しようとする古典的な恐ろしいダイヤモンドの問題です。

        人
       / \
     学生スタッフ
       \ /
        学部

しかし、通常の継承により、実際には次のようになります。

    人 人
      | | | |
     学生スタッフ
       \ /
        学部

したがって、Faculty のインスタンスには実際には 2 つの Person があり、2 つの名前を取得することになります。

上の最初の図のひし形を取得するには、仮想継承を使用します。

class Staff : public virtual Person {
};
class Student : public virtual Person {
};
于 2011-05-18T11:50:58.973 に答える
9

通常の多重継承では、共有基底クラスの複数のコピーを取得します。1 つのコピーが必要な場合は、仮想継承を使用します。

ウィキペディアでよく説明されています

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

あなたが期待したものを手に入れます

于 2011-05-18T11:49:05.773 に答える
2

2 つの異なるクラスから別々に継承しています。

仮想継承を使用する必要があります

于 2011-05-18T11:49:51.437 に答える
1

あなたは古典的なダイヤモンドの継承の問題に遭遇しました。C ++での多重継承の仕組みにより、実際にはinの2つの異なるコピーがあります。これは通常、次のような仮想継承を使用して解決できるため、とそのメンバーは1つだけです。nameFacultyPerson

class Student : public virtual Person {
};
class Staff : public virtual Person {
};

この場合、私はかなり確信していますが、あなたはこれをしたくありません。FacultyすべてがStudentANDメンバーであると想定するのは合理的ではないように思われるStaffため、このように表現するべきではありません。aFacultyは常にであると考えられるためStaff、単一の継承を使用してその関係をモデル化できます。次に、必要に応じて、で必要な学生からの共通コードを(無料の関数または別のクラスに)除外しFacultyます。

于 2011-05-18T13:30:14.197 に答える
0

多重継承の場合、派生クラスfacultyには の 2 つのコピーがありPersonます。1st からStudent2nd までStaff

参照するときはfaculty.Person::name、経由Studentまたは経由のいずれかを参照しますStaff。これはあいまいな状況であり、g++ でコンパイルすることさえできません。

MSVC では、最初に をFaculty継承してから を参照しているようです。そのため、最初の 2 行の出力は同じで、3 行目は異なります。StudentStafffaculty.Person::namefacutlty ==> Student ==> Person ==> name

于 2011-05-18T12:00:03.677 に答える
0

class Facultyは の 2 つのサブオブジェクトを継承しますclass Person。1 つは を介し​​てclass Student、もう1 つは を介し​​て継承されclass Staffます。

&faculty.Staff::nameclass Personを介して派生したサブオブジェクトのアドレスを返しますclass Staff

&faculty.Student::nameclass Personを介して派生したサブオブジェクトのアドレスを返しますclass Student

どちらも異なるサブ オブジェクトであるため、異なるアドレスになります。

于 2011-05-18T11:48:57.053 に答える
0

少し話が逸れますが....ほとんどの経験豊富な開発者は多重継承を避けています。維持するのが難しく、危険をはらんでいます。

于 2011-05-18T12:03:46.650 に答える