2011-05-18 89 views
8

我有以下代碼:關於C++多重繼承的問題?

#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** 

我不明白這一點。爲什麼Line 1Line 2中的地址與Line 3不同,而學生和工作人員都繼承了Person的名字?

回答

9

通過定期的多重繼承,您可以獲得共享基類的多個副本。如果你想要一個副本,使用虛擬繼承。

Wikipedia

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

很好地解釋會得到你你預計

0

class Faculty繼承class Person兩個子對象,一個通過class Student,另一個通過class Staff

&faculty.Staff::name返回通過class Staff派生的class Person的子對象的地址。

&faculty.Student::name返回通過class Student派生的class Person的子對象的地址。

兩者都是不同的子對象,因此不同的地址。

2

你是從兩個不同的類分別繼承。

當你做多重繼承這樣你得到的祖父類的兩個副本,你應該使用virtual inheritance

13

。這是典型的dreaded diamond問題,你試着這樣做:

 

     Person 
    /  \ 
    Student Staff 
     \  /
     Faculty 

但通過正常繼承你真正得到這樣的:

 
    Person Person 
     |  | 
    Student Staff 
     \  /
     Faculty 

所以沒什麼2人在學院的一個實例,這意味着你會得到2個名字。

要獲得上面的第一個圖中的鑽石,你想要使用virtual inheritance

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

+1得到最詳細的答案。我認爲這個ASCII藝術應該被接受爲 – 2011-05-18 13:20:51

+1

+1。 – 2011-05-18 16:55:14

0

多重繼承派生faculty類具有Person 2份。第一個通過Student和第二個通過Staff

當您參考faculty.Person::name時,它指的是通過Student或通過Staff。這是一個不明確的的情況,甚至不會用g ++編譯。

在MSVC,似乎因爲Faculty繼承StudentStaff,它是指faculty.Person::namefacutlty ==> Student ==> Person ==> name。這就是爲什麼前兩行輸出相同而第三行不同。

0

有點偏離主題,但....大多數有經驗的開發人員避免多重繼承。這是很難維持和充滿危險。

+3

你可以提供這些信息作爲評論:-) – NirmalGeo 2011-05-18 12:11:15

1

您遇到了經典的鑽石繼承問題。由於多重繼承在C++中的工作方式,實際上有兩個name的不同副本Faculty。這通常可以通過使用虛擬繼承這樣來解決,所以你只有Person一個實例及其成員:

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

我敢肯定,在這種情況下,但是你不希望這樣做。假設每個Faculty也是一個Student和一個Staff成員似乎並不合理,所以您不應該以這種方式表示它。看起來似乎是合理的,因爲Faculty將始終是Staff,所以您可以使用單一繼承來建模該關係。然後,如果需要,請將學生的常見代碼(免費功能或單獨的課程)分解出來,這在Faculty中也是需要的。