2013-03-14 150 views
-3

運行此程序時出現「分段錯誤」。輸出多態概念

f in xxx 
g in xxx 
f in yyy 
Segmentation fault 

但根據多態性概念,同樣的問題

class xxx{ 
     public: virtual void f(){cout<<"f in xxx"<<endl;}  //virtual function 
       virtual void g(){cout<<"g in xxx"<<endl;}  //virtual function 
}; 
class yyy:public xxx{    //yyy is derived from xxx 
     public: virtual void f(){cout<<"f in yyy"<<endl;} 
       void g(){cout<<"g in yyy"<<endl;} 
}; 
int main(int argc, char *argv[]) 
{ 
     xxx x1,*x; 
     yyy y1; 
     x=&x1; 
     x->f(); 
     x->g(); 
     x=(xxx*) &y1;  //parent class pointer having derived class address 
     x->f(); 
     x->g(); 
} 

- - 請在下面兩個程序

class xxx{ 
     public: virtual void f(){cout<<"f in xxx"<<endl;} //virtual function 
       virtual void g(){cout<<"g in xxx"<<endl;} //virtual function 
}; 
class yyy{   //yyy has no relation with xxx at this context 
     public: virtual void f(){cout<<"f in yyy"<<endl;} //virtual function but no relation with xxx class 
       void g(){cout<<"g in yyy"<<endl;} 
}; 
int main(int argc, char *argv[]) 
{ 
     xxx x1,*x; 
     yyy y1; 
     x=&x1; 
     x->f(); 
     x->g(); 
     x=(xxx*) &y1;  //one class pointer containing another class object address 
     x->f(); 
     x->g(); 
} 

的區分輸出

f in xxx 
g in xxx 
f in yyy 
g in yyy 
+0

你不需要打擾它。只要做:x = &y1; – 2013-03-14 19:08:04

+2

有什麼問題? – 2013-03-14 19:08:06

+0

尊敬的傑米格雷..嘗試你的想法時出現錯誤... x = &y1; //錯誤:不能轉換âyyy*â在xxx *â在作業謝謝... – 2013-03-27 05:48:47

回答

0

在你的第一個例子:

x=(xxx*) &y1;  //one class pointer containing another class object address 
    x->f(); 
    x->g(); 

變量x在其中有沒有關係xxx類的類yyy實際上是指向。 f()在兩者中都被聲明並且是唯一的虛擬函數使得它正常工作。由於g()是類xxx中的虛函數,但不是yyy中的虛函數,因此編譯器將生成代碼以調用虛函數g(),其中虛函數表(vtable)中的f()後面會發生一些垃圾, [虛擬函數的具體實現方式當然是一個實現細節,但期望每個類存儲某種函數的「表格」是公平的]。

它會給你更有趣的結果,如果你yyy被宣佈是這樣的:

class yyy{   //yyy has no relation with xxx at this context 
     public: virtual void g(){cout<<"g in yyy"<<endl;} //virtual function but no relation with xxx class 
       void f(){cout<<"f in yyy"<<endl;} 
}; 

它會告訴你,這得「克YYY」爲號召f()的結果,和然後致電g() ...因爲虛擬函數的工作方式並不是它們是基於它們的名字被調用的,而是它們在類中的「順序」[再次,它的工作原理是實現細節,並且由於我們正在處理「未定義的行爲」,編譯器還可以在屏幕上閃爍紅色文本或在緊急呼叫中像救護車一樣打印「答案爲42」 - 但這種情況發生的可能性比我在典型的C++編譯器實現中所描述的要少) 。

在你的第二個情況下,因爲xxxvirtual被繼承到yyy,功能g()yyy虛擬爲好,因爲「它的工作原理,你期望它」,因爲你在做什麼是你應該什麼去做。

還要注意,有C++風格的轉換可以幫助您避免發生這類錯誤 - 如果您做錯了,它會在編譯時(static_cast)或在使用dynamic_cast的地方出現錯誤信息編譯器無法在編譯時確定類型,因此它會給出nullptr,這是一個明顯的錯誤指示。

2

在第一種情況下,由於您告訴編譯器像&y1指向xxx時那樣,該投射會產生垃圾。在第二種情況下,yyyxxx,所以將指針指向yyy以指向xxx是安全的,因爲它的之一。

如果您有指向卡車的指針,則可以將其作爲指向車輛的指針,因爲卡車是車輛。但是,如果你有一個指向花朵的指針並將它作爲指向車輛的指針,它本質上是一個垃圾指針,並且取消引用它是未定義的行爲。

儘管如此,您應該使用C++風格強制轉換而不是C風格強制轉換。如果你不得不表達預期的語義,那麼捕捉這種錯誤的機會就會更大。 (編寫第一個代碼的程序員是否認爲它可以起到static_cast的作用?或者他們認爲它會起到reinterpret_cast的作用?額外的思考選擇一個,或者在沒有轉換的情況下執行操作可能避免了錯誤。)