C++為什麼要將解構函式設為虛擬函式
阿新 • • 發佈:2021-02-18
首先我們知道虛擬函式是實現執行期的多型的。
根據型別相容原則,在需要基類指標的地方,都可以用派生類的指標去代替。
如下程式碼,就實現了多型。
#include<bits/stdc++.h>
using namespace std;
class A{
public:
A(){
}
~A(){
}
virtual void fun(){
cout<<1<<endl;
}
};
class B:public A{
public:
B(){
}
~B(){
}
virtual void fun(){
cout<<2<<endl;
}
};
int main(){
A* testA=new A();
testA->fun();
delete testA;
A* testB=new B();
testB->fun();
delete testB;
return 0;
}
輸出:
其實,上面程式碼是存在記憶體洩漏的。
#include<bits/stdc++.h>
using namespace std;
class A{
public:
A(){
}
~A(){
cout<<"A over"<<endl;
}
virtual void fun(){
cout<<1<<endl;
}
};
class B:public A{
public:
B(){
}
~B(){
cout<<"B over"<<endl;
}
virtual void fun(){
cout<<2<<endl;
}
};
int main(){
A* testA=new A();
testA->fun();
delete testA;
cout<<endl;
A* testB=new B();
testB->fun();
delete testB;
return 0;
}
輸出:
可以發現testA沒有問題。
但是testB只有類A部分被析構了,而類B還沒有析構,這裡存在了記憶體洩漏
那麼將解構函式定義為虛擬函式後呢
#include<bits/stdc++.h>
using namespace std;
class A{
public:
A(){
}
virtual ~A(){
cout<<"A over"<<endl;
}
virtual void fun(){
cout<<1<<endl;
}
};
class B:public A{
public:
B(){
}
virtual ~B(){
cout<<"B over"<<endl;
}
virtual void fun(){
cout<<2<<endl;
}
};
int main(){
A* testA=new A();
testA->fun();
delete testA;
cout<<endl;
A* testB=new B();
testB->fun();
delete testB;
return 0;
}
輸出:
這樣就沒有問題了
所以,將解構函式設為虛擬函式,是為了防止記憶體洩漏。
如果存在用基類指標指向派生類物件,這樣子可以使得基類和派生類的解構函式都被呼叫,不會造成記憶體洩漏。如果不把解構函式定義為虛擬函式,那麼只會呼叫基類的解構函式。