class A {
public:
A() { printf("A \n"); }
~A() { printf(" ~A \n"); } // 這里不管寫不寫virtual,刪除B對象的時候,都會被執行。因為這個例子是B*指針指向B對象,不是A*指針指向B對象。
};
class B : public A
{
public:
B() { printf("B \n"); }
~B() { printf("~B \n"); }
};
int main(int argc, char* argv[])
{
B* b = new B;
delete b;
return 0;
}
int main(int argc, char* argv[])
{
B b; // 雖然正確,但其實是非正常情況,因為你防不住程序員定義A* a = new B(); 這樣就錯了。
return 0;
}
執行結果:
A
B
~B
~A
結論:刪除子類指針,無論如何會自動調用祖先類的析構函數(即使祖先類的習慣函數不是虛擬的),雖然這是非正常情況,但還是記一下。
------------------------------------------------------------
class A {
public:
A() { printf("A \n"); }
virtual ~A() { printf(" ~A \n"); } // 增加了虛擬關鍵字
};
class B : public A
{
public:
B() { printf("B \n"); }
~B() { printf("~B \n"); }
};
int main(int argc, char* argv[])
{
A* a = new B;
delete a;
return 0;
}
執行結果(正常情況,子類祖先類的析構函數都是虛擬的,這樣刪除祖先類指針、子類對象的時候,可正確同時調用子類和祖先類的析構函數):
A
B
~B
~A
但是如果去掉 virtual(這里是A*指針指向B對象),改一下立刻有效果,變成了錯誤(錯誤情況)。
執行結果:
A
B
~A
總結:自己類型的指針指向自己的對象,怎么樣都沒有問題(不管父類析構函數寫不寫virtual)。只有基類指針指向子類對象的時候,一定需要virtual關鍵字的配合,才能正確的工作