作者DEATHX (幽光)
看板C_and_CPP
標題Re: [問題] 一個物件以及指標的問題。
時間Thu Nov 4 00:47:08 2010
剛剛看完 <戰乙女的凌辱> 就看到這麼一篇文章,
又這麼剛好伸手拿衛生紙的右手碰到了書架上一本書,
書掉到地上,正好提到了你的問題:
-----------------------書中原文---------------------------
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