基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?
如題,當一個類為基類的時候,通常其析構函數被聲明為虛函數,這是為啥?
class BaseCls{
public:
BaseCls() { printf("BaseCls()n"); }
~BaseCls() { printf("~BaseCls()n"); }
void test_func() { printf("Base::test_func()n"); }
};
class SubCls : public BaseCls
{
public:
SubCls() { printf("SubCls()n"); }
~SubCls() { printf("~SubCls()n"); }
void test_func() { printf("SubCls::test_func()n");
};
int main(void)
{
BaseCls *base = new SubCls;
base->test_func();
delete base;
return 0;
}
編譯運行:
在main()函數中,定義了BaseCls類型指針,根據賦值兼容性原則,該指針可以指向動態生成子類SubCls對象的地址,此時動態生成的SubCls對象已經被充當基類使用,因為BaseCls中的test_func()函數是普通函數(并非虛函數)不能發生多態,所以打印的是基類的”Base::test_func()n”。
代碼”delete base;”我們希望用來釋放SubCls的空間,即調用SubCls的析構函數,釋放完畢后BaseCls的析構函數。然而編譯器只是根據指針類型是BaseCls而只是調用BaseCls的析構函數,SubCls的析構函數得不到調用,若在SubCls構造函數中動態分配的空間,在析構函數釋放空間,那么這樣就造成內存泄漏了。
如何改進?讓基類BaseCls的析構函數聲明為虛函數,使其在delete base時發生多態即可:
class BaseCls{
public:
//...
virtual ~BaseCls()
{
printf("~BaseCls()n");
}
//...
};
編譯運行:
將構造函數中聲明為virtual后,編譯器就不會簡單的只根據base指針的類型而決定調用對象的構造函數,而是依據指針base所指向的實際對象而調用其構造函數,這不就是多態嗎?
最后,再補充兩個問題?
(1) 析構函數可以被聲明為虛函數,那構造函數可以聲明為虛函數嗎?
- 答案是不可以。因為虛函數的調用依靠于虛函數表。然而在構造函數執行完畢后,虛函數表指針才被正確初始化。
(2) 構造函數不可以被聲明為虛函數,那么構造函數的實現體中,可以實現多態嗎?
- 答案還是不可以。因為析構函數一旦被調用,虛函數表指針就會銷毀了。那么同理,在構造函數中實現體中也不可能發生多態行為,因為在構造函數執行時,虛函數表指針還沒被正確初始化。
總結
以上是生活随笔為你收集整理的基类的析构函数不能被继承。_为什么要把C++类中的析构函数声明为虚函数?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中str和int区别_Pyt
- 下一篇: python import出错_pyth