我有一個自定義類Student對象的數組。 CourseStudent和ResearchStudent都是從Student繼承而來的,Student的所有實例都是其中的一個。從超類指針訪問子類成員C++
我有一個函數要經過陣列,確定每個學生的亞型,然後調用它們亞型特異性成員函數。
的問題,因爲這些功能都沒有超載,他們沒有在學生中發現,所以編譯器大吵大鬧。
如果我有一個指向學生,有沒有一種方式來獲得一個指向學生的亞型?我是否需要在這裏進行某種假轉換以解決編譯時錯誤?
我有一個自定義類Student對象的數組。 CourseStudent和ResearchStudent都是從Student繼承而來的,Student的所有實例都是其中的一個。從超類指針訪問子類成員C++
我有一個函數要經過陣列,確定每個學生的亞型,然後調用它們亞型特異性成員函數。
的問題,因爲這些功能都沒有超載,他們沒有在學生中發現,所以編譯器大吵大鬧。
如果我有一個指向學生,有沒有一種方式來獲得一個指向學生的亞型?我是否需要在這裏進行某種假轉換以解決編譯時錯誤?
您需要動態演員陣容:
Student * s = new ...; // create student of some sort
if (ResearchStudent * r = dynamic_cast<ReasearchStudent*>(s)) {
r->ResFunc();
}
else if (CourseStudent * c = dynamic_cast<CourseStudent*>(s)) {
c->CourseFiunc();
}
else {
throw "unknown student type";
}
請注意,它使用由編譯器維護的類型信息,前提是該類至少有一個虛函數 - 如果其他所有函數都失敗,則使析構函數爲虛擬(因爲它必須在此情況下)。你應該總是喜歡這種方法來維護你自己的類型信息。
您需要static_cast
。由於這些函數不是基類的虛擬成員,因此不能通過指向基類的指針來調用它們。您需要明確地轉換爲對象的實際類型。
這個問題通常是最好的虛擬功能解決了 - 你並不需要的對象類型在你的代碼檢查了,都會有漏洞越少的代碼和麪較少。
這是幾乎可以肯定在基類中使用純虛成員函數,然後在派生類中,你做真正的工作壓倒一切的情況下。
,最好的辦法是使用虛函數:
class Student
{
// ...
virtual void SpecificFunction() = 0; /* = 0 means it's abstract; it must be implemented by a subclass */
// ...
};
class CourseStudent
{
void SpecificFunction() { ... }
};
然後,你可以這樣做:
Student *student;
student->SpecificFunction();
A(壞)的替代,可以使用dynamic_cast
:
Student *student;
CourseStudent *cs = dynamic_cast<CourseStudent *>(student);
if (cs) {
/* student is a CourseStudent.. */
cs->SpecificFunction();
}
虛擬函數在這裏是不合適的,因爲子類成員函數是特定於這些子類的(例如,CourseStudent有一個單元列表,而ResearchStudent沒有,因此ResearchStudent中的getUnits()函數實現將沒有意義所有)
我對動態和靜態轉換(cplusplus.com typecasting)有一些瞭解,在這種情況下,我認爲靜態轉換更合適。
一個的static_cast的一般缺點是,它在運行時不執行任何檢查,以確保被鑄造到一個子類型的對象是實際上是亞型而不是其他。在這種情況下,我在執行類型之前特別檢查類型(使用在子類構造函數中設置的私有數據成員並且沒有增變器),所以只要我的檢查是好的,靜態轉換就不會有問題。靜態轉換更高效,因爲動態轉換需要更多運行時資源來執行類型檢查。
如果有任何成員不是預期類型的機會,靜態轉換就不合適,所以我會去動態轉換(這是一個賦值,因此一旦它被提交,代碼將不需要保持不變,所以不會有人在後面搞亂它)。
我知道這是很久以前,但我想說謝謝;我今天剛剛面對一個非常類似的問題,您的回答爲我提供了完全所需的解決方案! – GarrickW 2012-02-18 17:32:53
@GarrickW很高興聽到它仍然有用 - 使它值得努力尋找想法的解決方案。 – 2012-02-23 03:35:08
所有的事情都是平等的,Java/C#的視角會說動態轉換更好,因爲這樣你的指針就按你打算使用它的方式被輸入,而不是一個'Student', SpecificFunction()'給出'CourseStudent'的返回值。但我敢肯定,所有的事情都不一樣 - 所以使用動態演員有什麼不好? – 2012-03-21 16:08:36