2013-02-14 60 views
1

我有一個基類Student(),有兩個派生類GradStudent()和UndergradStudent()。C++創建一個多派生類的數組

基類有一個名爲getInfo()的函數,兩個派生類有它們自己的getInfo()函數。

該任務是創建一個學生數組並存儲該數組中每個類的對象。然後我從每個(分別使用基類函數的版本)調用getInfo(),然後從兩個派生類中調用getInfo()函數。

對於我的生活,我無法弄清楚如何做到這一點。這是我到目前爲止有:

(我想我應該在這裏提一下,我不能修改基類)

Student *classRoom[3]; 

    Student base ("Jim", "Bean", 1111); 
    classRoom[0] = &base; 

    GradStudent test ("Jack", "Daniels", 1234, 'M', "Art"); 
    classRoom[1] = &test; 

    UndergradStudent ust1 ("Johnny", "Walker", 1235, 1); 
    classRoom[2] = &ust1; 

    cout << classRoom[1]->getInfo(); 

任何人都可以點我在正確的方向?我會說,具體說明它必須是一個數組,所以沒有矢量解決方案請(仍然不熟悉它們)。

+0

這不起作用?它看起來應該。有什麼問題? (儘管這樣做很愚蠢) – Pubby 2013-02-14 10:23:56

+4

只要'getInfo'是'virtual' - 它應該是,因爲它在基類中,所以你不能改變 - 這應該可以工作。那究竟是什麼問題? – Jon 2013-02-14 10:24:15

+1

向我們展示來自Student,GradStudent和UndergradeStudent的類定義,並指定您在代碼中遇到的問題 – 2013-02-14 10:25:09

回答

0

如果getInfo()成員函數不是虛擬的,則您的任務的第一部分將迭代您的數組,並在每個實例上調用getInfo()

對於第二部分,您必須將派生類的實例向下轉換爲它們的實型,以便調用派生類的實際成員函數。

此外,我建議您填寫您的數組中的下列方式:

classRoom[0] = new Student("Jim", "Bean", 1111); 
classRoom[1] = new GradStudent("Jack", "Daniels", 1234, 'M', "Art"); 
classRoom[2] = new UndergradStudent ("Johnny", "Walker", 1235, 1); 

不要忘記在程序結束時刪除它們。

+0

我其實是想這樣做,但編譯器扔了一個合適的,因爲我有析構函數。 – user2036101 2013-02-14 10:47:16

+0

爲什麼它會因爲你有析構函數而發病? – dutt 2013-02-14 10:47:46

+0

呵呵。只是試了一遍,它的工作。我想我從最後一次嘗試之後改變了一些東西(它遲到了......我沒有想好)。 Thnaks! – user2036101 2013-02-14 10:52:54

2

如果您甚至不能修改派生類,那麼很難在他們不知道的情況下調用GetInfo,它們是特定類型的。也許你需要使用直接的解決方案:

GradStudent gradStudent; 
cout << gradStudent.GetInfo(); 

或者你可以嘗試檢查,如果學生指定的派生類的,但IMO這是非常醜陋的和危險的(在擴展代碼而言):

for (int i = 0; i < 3; i++) 
{ 
    GradStudent * gs = dynamic_cast<GradStudent *>(classRoom[i]); 
    if (gs != nullptr) 
     cout << gs->GetInfo(); 
    else 
    { 
     UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(classRoom[i]); 
     if (ugs != nullptr) 
      cout << ugs->GetInfo(); 
     else 
      cout << classRoom[i]->GetInfo(); 
    } 
} 

我不得不說,多態是專門爲處理像這樣的情況而創建的,並且GetInfo在基類中不是虛擬的是嚴重的架構缺陷。

此外:如果您在玩指針,請避免將地址複製到局部變量。這可能是危險的。相反,分配和取消分配手動內存:

classRoom[0] = new Student; 
classRoom[1] = new GradStudent; 
classRoom[2] = new UndergradStudent; 

// Process data 

for (int i = 0; i < 3; i++) 
    delete classRoom[i]; 

邊緣:我討厭像任務:做X,而無需使用Y(其中Y爲專門設計來解決X)。


編輯:(響應評論)

你問,虛函數將如何解決這個問題。假設有一段時間,Student::GetInfo是虛擬的。讓我們分析下面的幾段代碼:

Student * student = new Student; 
student->GetInfo(); // Student::GetInfo is called 

GradStudent * gradStudent = new GradStudent; 
gradStudent->GetInfo(); // GradStudent::GetInfo is called 

現在沒什麼讓人驚訝的。

Student * student = new GradStudent; 
student->GetInfo(); 
// if Student::GetInfo is virtual, GradStudent::GetInfo is called here 
// if Student::GetInfo is not virtual, Student::GetInfo is called here 

現在仔細閱讀。如果Student::GetInfo是虛擬的並且在GradStudent類中實現,則將調用GradStudent::GetInfo,儘管事實上它被稱爲Student變量。 但是,如果Student::GetInfo不是虛擬,在以前的情況下,Student::GetInfo將被調用。這基本上是虛擬功能的工作原理。

就你而言,你有一個Student *變量數組 - 你並不完全知道它們是否是Student s,GradStudent s或UndergradStudent s。由於您的Student::GetInfo不是虛擬的,所以在這些變量上調用此方法將始終導致調用Student::GetInfo,無論它們的實際類型如何。

在這種情況下,我能想到的唯一的解決辦法是設法猜測,其實它們是類:

Student * student = new UndergradStudent; 

Student * s = student; // Ok 
GradStudent * gs = dynamic_cast<GradStudent *>(student); // Not true, will return NULL/nullptr 
UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(student); // Ok 

這樣,您就可以恢復到原來的類型,並調用實際的變量類型的GetInfo

請注意,這是一個醜陋的解決方案,這種問題可以通過虛擬函數來解決。

C++ FAQ是進一步瞭解虛擬功能的好地方。

+0

感受我的痛苦。我考試中的一半問題是「讓我製作最笨拙,設計可怕的代碼,然後閱讀它。」 而我所有的作業都完全和你描述的一樣。 非常坦率地說,我討厭指針,並避免他們像瘟疫,但.. – user2036101 2013-02-14 10:50:19

+0

當我在學習時,振作起來,曾經在一個大討論會上,我得到了一個使用未分配變量的源代碼。這是最有趣的座談會,也是唯一一個可以獲得110%分數的學員:)祝您考試順利! – Spook 2013-02-14 10:53:31

+0

所以,你不知道如何區分來自基類的getInfo()和來自它的實際類的getInfo()之間的調用? 虛擬修復事情究竟如何(如果解釋太多,你能指出我朝着正確的方向嗎?) – user2036101 2013-02-14 10:59:59

0

我對這個問題有點困惑,但是這是我從它那裏得到:

迭代通過每個元素classRoom,呼籲每個元素getInfo()。然後輸出test.getInfo()ust1.getInfo()的結果。

如果這是正確的,我覺得何老師可能是想指出的是,如果在其getInfo()被調用的對象是派生類類型(GradStudentUndergradStudent)中的一個,儘管指針該對象的類型爲Student*,派生類版本getInfo()將始終被調用。

這是因爲即使你在一個Student*調用getInfo()getInfo()將綁定到在運行時的派生類實現(因爲getInfo()是虛擬的)。

+0

其實他告訴我使用getinfo()函數中的相同數組元素 – user2036101 2013-02-14 12:22:30