析构函数为什么写成虚函数?
由于類的多態(tài)性,基類指針可以指向派生類的對象。如果刪除該基類的指針,就會(huì)調(diào)用該指針指向的派生類的析構(gòu)函數(shù),而派生類的析構(gòu)函數(shù)又會(huì)自動(dòng)調(diào)用基類的析構(gòu)函數(shù),這樣整個(gè)派生類的對象被完全釋放。·
如果析構(gòu)函數(shù)不被聲明成虛函數(shù),則編譯器實(shí)施靜態(tài)綁定,在刪除基類指針時(shí),只會(huì)調(diào)用基類的析構(gòu)函數(shù)而不調(diào)用派生類析構(gòu)函數(shù),這樣就會(huì)造成派生類對象析構(gòu)不完全,造成內(nèi)存泄漏。
(簡而言之,如果一個(gè)類將來打算作為基類,就把析構(gòu)函數(shù)寫成虛析構(gòu)函數(shù)。)
1、當(dāng)基類中的析構(gòu)函數(shù)沒有寫成虛析構(gòu)函數(shù)時(shí):
#include <iostream> using namespace std;class Parent { public:Parent(){cout<<"Parent construct function"<<endl;}~Parent(){cout<<"Parent destructor function"<<endl;} };class Son:public Parent { public:Son(){cout<<"Son construct function"<<endl;}~Son(){cout<<"Son destructor function"<<endl;} };int main() { Parent *p=new Son();delete p;p=NULL;return 0; } 運(yùn)行結(jié)果: Parent construct function Son construct function Parent destructor function當(dāng)基類析構(gòu)函數(shù)寫成虛析構(gòu)函數(shù)時(shí):
#include <iostream> using namespace std;class Parent { public:Parent(){cout<<"Parent construct function"<<endl;}virtual ~Parent(){cout<<"Parent destructor function"<<endl;} };class Son:public Parent { public:Son(){cout<<"Son construct function"<<endl;}~Son(){cout<<"Son destructor function"<<endl;} };int main() { Parent *p=new Son();delete p;p=NULL;return 0; } 運(yùn)行結(jié)果: Parent construct function Son construct function Son destructor function Parent destructor function但存在一種特例,在模板CRTP中,不應(yīng)該將析構(gòu)函數(shù)聲明為虛函數(shù),理論上所有的父類函數(shù)都不應(yīng)該聲明為虛函數(shù),因?yàn)檫@種繼承方式,不需要虛函數(shù)表。
析構(gòu)函數(shù)可以是純虛函數(shù),含有純虛函數(shù)的類是抽象類,此時(shí)不能被實(shí)例化。但派生類中可以根據(jù)自身需求重新改寫基類中的純虛函數(shù)。
構(gòu)造函數(shù)不能定義為虛函數(shù)。在構(gòu)造函數(shù)中可以調(diào)用虛函數(shù),不過此時(shí)調(diào)用的是正在構(gòu)造的類中的虛函數(shù),而不是子類的虛函數(shù),因?yàn)榇藭r(shí)子類尚未構(gòu)造好。
虛函數(shù)對應(yīng)一個(gè)vtable(虛函數(shù)表),類中存儲(chǔ)一個(gè)vptr指向這個(gè)vtable。如果構(gòu)造函數(shù)是虛函數(shù),就需要通過vtable調(diào)用,可是對象沒有初始化就沒有vptr,無法找到vtable,所以構(gòu)造函數(shù)不能是虛函數(shù)。
總結(jié)
以上是生活随笔為你收集整理的析构函数为什么写成虚函数?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: new / delete与malloc
- 下一篇: a和a有什么区别?