C++基類解構函式宣告為虛擬函式
先來看幾段程式例子:
1. 將基類解構函式宣告為虛擬函式
#include <iostream>
using namespace std;
class Person{
public:
virtual ~Person(){ //declare destructor as a virtual function
cout <<"Person::~Person()" << endl;
}
};
class Student : public Person{
public:
~Student(){ // virtual or not is OK
cout<< "Student::~Student()" << endl;
}
};
int main(){
Person *pt1 = new Person;
Person *pt2 = new Student; // base class pointer point to derived class
// Student *pt3 =new Person; // derived class pointer can not point tobase class
Student *pt4 = new Student;
delete pt1;
cout <<"*********" << endl;
delete pt2;
cout <<"*********" << endl;
//delete pt3;
//cout <<"*********" << endl;
delete pt4;
cout <<"*********" << endl;
return 0;
}
執行結果:
2.不將基類解構函式宣告為虛擬函式:
#include <iostream>
using namespace std;
class Person{
public:
~Person(){ //declare destructor as a virtual function
cout <<"Person::~Person()" << endl;
}
};
class Student : public Person{
public:
~Student(){ // virtual or not is OK
cout<< "Student::~Student()" << endl;
}
};
int main(){
Person *pt1 = new Person;
Person *pt2 = new Student; // base class pointer point to derived class
// Student *pt3 =new Person; // derived class pointer can not point tobase class
Student *pt4 = new Student;
delete pt1;
cout <<"*********" << endl;
delete pt2;
cout <<"*********" << endl;
//delete pt3;
//cout <<"*********" << endl;
delete pt4;
cout <<"*********" << endl;
return 0;
}
執行結果:
可以看出:
在用基類指標指向派生類時,
在基類解構函式宣告為virtual的時候,delete基類指標,會先呼叫派生類的解構函式,再呼叫基類的解構函式。
在基類解構函式沒有宣告為virtual的時候,delete基類指標,只會呼叫基類的解構函式,而不會呼叫派生類的解構函式,這樣會造成銷燬物件的不完全。
分析:
Person *pt2 = new Student;
pt2的靜態型別為Person,而動態型別為Student,
當解構函式為虛擬函式時,為動態繫結,delete pt2,會呼叫動態型別即派生類的解構函式,由於繼承關係,也會呼叫基類的解構函式;
而當解構函式為非虛擬函式時,為靜態繫結,delete pt2,會呼叫靜態型別即基類的解構函式,而不會呼叫派生類的解構函式。
3.總結:
警告: deletingobject of polymorphic class type which has non_virtual destructor might causeundefine behavior
原來如果基類裡有虛擬函式,定義了基類指標指向派生類,就會需要定義基類虛析構,這樣,基類指標析構的時候,就會先析構派生類,再析構基類。
如果不定義虛析構,就會基類指標直接析構基類。這樣派生類物件銷燬不完整。所以編譯器會告訴你,警告你的。
在程式碼設計的時候,如果派生類有自己在heap中申請的空間,而且會用到派生類向基類的轉化,那麼一定要宣告虛解構函式。若果沒有同時滿足上述兩個條件, 則不要宣告虛解構函式(申明虛解構函式和申明虛成員函式一樣,都會佔用一個virtualpointer)。
在程式碼設計的過程中,最好是顯式的同時宣告基類和派生類的解構函式為虛擬函式。
確保使用使用指向派生類物件的基類指標釋放派生類物件的記憶體空間時,
派生類的解構函式可以正常的呼叫。就是所謂的多型吧
如果你用基類的指標指向一個派生類物件。再刪除這個物件的時候,只會執行基類的解構函式而不會執行派生類的析構。只有把基類的析構設為虛擬函式的時候才會執行派生類的析構。
如果需要從基類來刪除物件的話,物件的解構函式需要為virtual 。