2016-09-20 77 views
0
#include <iostream> 
using namesapce std; 
class A 
{ 
    public: 
     virtual ~A(){cout<<"delete A"<<endl}; 
}; 
class B: public A 
{ 
    public: 
     B(int n):n(n){} 
     void show(){cout<<n<<endl;} 
     ~B(){cout<<"delete B"<<endl;} 
    private: 
     int n; 

} 
int main() 
{ 
    A *pa; 
    B *pb = new B(1); 
    pa = pb; 
    delete pa; 
    pb->show(); 
    return 0; 
} 

當CALSS A的析構函數是virtual ~A(){...},程序的輸出: delete B delete A 1 當類A的析構函數是~A(){...},progarm的輸出: delete A 0 爲什麼n的值是不同的時,類A的析構函數是虛擬非虛擬?當調用B的析構函數銷燬對象時,爲什麼會話成員n仍然存在?當A類的析構函數是虛擬的還是非虛擬的時,爲什麼B的calss成員n有不同的值?

+0

你明白虛擬函數是什麼嗎? – Barry

+1

什麼是'pb-> show(){};'? – AnT

+0

你可能想閱讀這個http://www.learncpp.com/cpp-tutorial/122-virtual-functions/ –

回答

1
A *pa; 
B *pb = new B(1); 
pa = pb; 

這就是所謂的上傳。每當向上轉換完成時,基類的析構函數應該是虛擬的。

沒有虛擬基本的析構函數,刪除pa將只調用不希望的基類析構函數,因爲它的派生類對象永遠不會被銷燬並導致內存泄漏。

基類的虛析構函數會調用第一個派生類的析構函數,然後它會破壞自己,這是期望的行爲,並且不會因爲上傳而導致任何泄漏。

+0

簡而言之,如果沒有虛擬基類析構函數,你會得到_undefined behavior_。 – qxz

+0

爲什麼n的價值不同? – PengWin

+0

waht是未定義的行爲,爲什麼編譯器告訴編碼器有錯誤? – PengWin

1

您的程序展示未定義的行爲。這是你「爲什麼」問題的唯一答案。

首先,如果析構函數A不是虛擬的,那麼在你的代碼中做delete pa會導致未定義的行爲。試圖以delete類型B的對象通過指向父類型A *的指針導致未定義的A析構函數的行爲不是虛擬的。

其次,pb->show()似乎是試圖調用一個已經被破壞的對象的方法。行爲也是未定義的,無論析構函數是否爲虛擬的。

相關問題