看板 C_and_CPP 關於我們 聯絡資訊
剛剛看完 <戰乙女的凌辱> 就看到這麼一篇文章, 又這麼剛好伸手拿衛生紙的右手碰到了書架上一本書, 書掉到地上,正好提到了你的問題: -----------------------書中原文--------------------------- C++讓你使用父類別指標來指向子類別物件.然而,當我們這麼做時後, 編譯器有時會產生混淆.例如,請思考以下宣告: class Mammal { public: void Eat(); } class Cat : public Mammal { public: void Sleep(); } 則以下敘述是合法的: Mammal *garfield = new Cat; 請注意,記憶體中實體化的是Cat物件,所以即使garfield宣告為指向Mammal 的指標,但它卻是指向Cat. Cat物件擁有兩個成員函式: Eat()和Sleep(). 然而,使用garfield指標只能夠直接呼叫Eat()函式. 例如,以下敘述是合法並且可以通過編譯: garfield->Eat(); 編譯器認為garfield指向Mammal,並且Mammal類別包含Eat()的成員函式. 以下的敘述則無法通過編譯: garfield->Sleep(); //將會產生編譯錯誤 編譯器無法在Mammal類別中找到Sleep()函式,而這是預期中的狀況, 因為Mammal類別並沒有包含Sleep()函式.為了使用父類別指標來呼叫子類別的函式, 該指標必須依據繼承階層,向下轉換成適當的物件類別. 例如,為了呼叫Sleep()函式,garfield指標必須轉換成Cat指標, 而這可以透過建立Cat指標來加以完成,如下所示: Cat *temp = (cat *)garfield; temp->Sleep(); 另一種作法是,你可以在一個敘述式中轉換garfield物件並且呼叫Sleep()函式. ((Cat *)garfield)->Sleep(); 在其他情況下,當你依據繼承階層來進行向下轉換時,你必須十分謹慎. 非法的轉換動作會讓你的程式在執行期間異常終止.為了說明這種情況, 以下的程式碼宣告一個也是繼承Mammal的Dog類別: class Dog : public Mammal { public: void Sleep(); } 雖然以下的第二個敘述不合法,但是下列敘述依然可以通過編譯: Mammal *garfield = new Cat(); ((Dog *)garfield)->Sleep(); 編譯器在Dog類別找到Sleep()函式,並且假設該敘述是合法的. 在執行期間,當garfield指標轉換到Dog時,則結果是無法預測的, 而且該程式可能會產生嚴重錯誤. --------------------該章節完------------------------------ 我把用好的衛生紙丟掉,摸了摸發疼的LP. 在順便看看書的標題 <C++與MFC 視窗程式設計> Richard F. Raposa著 陳智湧,歐世亮,林志偉編譯 全華出版 下次我學乖了,處理個人庫存千萬不要開ptt,免得清槍清到一半又熄火. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.161.187.77
loveme00835:所以最好是用 dynamic_cast 才能知道轉成不成功 11/04 00:48
james732:不過 dynamic_cast 有效能上的問題...有一好沒兩好... 11/04 00:49
loveme00835:都要用多型了, 沒差啦~ 就是要全OO阿! 11/04 00:51
elfkiller:看c++清槍亦是神人乎 11/04 00:56
StephenNash:嗯,謝謝這位…槍俠!?的教導! 11/04 01:08