2010-08-22 77 views
11

(原諒提前noob問題)C++:多重繼承與多態性

我有4類:

class Person {}; 
class Student : public Person {}; 
class Employee : public Person {}; 
class StudentEmployee : public Student, public Employee {}; 

本質Person是基類,其直接由兩者StudentEmployee子類。 StudentEmployee採用多重繼承的子類StudentEmployee

Person pat = Person("Pat"); 
Student sam = Student("Sam"); 
Employee em = Employee("Emily"); 
StudentEmployee sen = StudentEmployee("Sienna"); 


Person ppl[3] = {pat, sam, em}; 
//compile time error: ambiguous base class 
//Person ppl[4] = {pat, sam, em, sen}; 

當我使用的Person陣列,基類,我可以把Person和所有它的子類的此陣列內。除了StudentEmployee,給出了歧義基類的原因。

鑑於StudentEmployee保證具有Person的所有方法和屬性,因此StudentEmployee被認爲是Person的一個子類?

  • 如果是這樣,爲什麼編譯器不允許我將一個對象分配給它的超類型的變量?
  • 如果沒有,爲什麼不;那麼完成這件事的正確方法是什麼?

乾杯


編輯:搶先,這個問題是不一樣的下面的任一:
polymorphism relates inheritance
Inheritance mucking up polymorphism in C++?

回答

13

StudentEmployee當然是Person的子類。問題是這樣的兩次:它間接繼承Person兩次(一次通過Student和一次通過Employee),這就是爲什麼你得到「不明確的基類」錯誤。爲了確保StudentEmployee既繼承Person一次,你必須使用虛擬繼承,就像這樣:

class Person {}; 
class Student : public virtual Person {}; 
class Employee : public virtual Person {}; 
class StudentEmployee : public Student, public Employee {}; 

這將解決您的錯誤。

儘管如此,代碼還存在另一個大問題,它叫做slicing

當你這樣做:

Person ppl[3] = {pat, sam, em}; 

3個Person對象數組將被創建,但這些對象將使用Person類的隱含定義拷貝構造函數複製構造。現在,問題在於數組中的對象將只是Person對象,而不是您希望它們的子類的對象。

要解決這個問題,你將不得不作出一個指針數組來Person對象,像這樣:

Person* ppl[] = {new Person("Pat"), new Student("Sam"), 
       new Employee("Emily"), new StudentEmployee("Sienna")}; 

Person* ppl[] = {&pat, &sam, &em, &sen}; 
+0

但是,很明顯,像這樣調用新內存幾乎肯定會導致內存泄漏 – Falmarri 2010-08-22 11:13:00

+1

+1的切片。並且爲了防止bguiz不知道,這也可能是Person * ppl [] = {&pat,&sam,&em,&sen }; - 這兩個選項的內存管理略有不同。 – Michael 2010-08-22 11:19:57

+0

@Falmarri:爲什麼?你仍然有指針數組。 – Job 2010-08-22 11:31:21

3

有從對象兩個同樣可能的路徑鍵入StudentEmployee將是Person

對於StudentEmployee類,您都需要使用關鍵字virtual。請參閱FAQ 25.8實際上要經過整個部分。

+0

謝謝,那篇文章一針見血的頭! – bguiz 2010-08-22 10:48:55