天天看點

再說c++虛析構函數

關于c++類中的虛析構函數。我寫這篇部落格是為了得出如下3點結論。

1.所有基類的析構函數,都應該聲明為虛析構函數!這也是c++标準所指定的。      
2.如果設計一個類,可能會被後來的其他類所繼承,我們一定要将它的析構函數聲明為虛析構。否則被繼承會出現記憶體洩漏等意想不到的問題。      
3.如果我們要去繼承另外一個類,首先一點是要保證被繼承的類的析構函數已經聲明為了虛析構函數!      

對以上3點,如果你深有理會,如下内容可以不看,不要浪費時間。如果沒有很深的概念,可以參考一下。如有問題,希望在評論區或其他方式給我指點,謝謝。

非繼承類的析構函數執行會有如下操作:

1、執行析構函數中的代碼

2、如果所在類有成員變量(類對象),再執行類成員變量的析構函數

普通析構函數:

以如下代碼為例

(表示很讨厭上面的水印)

析構順序:      
1、執行析構函數中的代碼

2、如果所在類有成員變量(類對象),再執行類成員變量的析構函數
      
再說c++虛析構函數
以上内容很好了解,因為隻是單個類對象的析構,當然也關系到類的組合。      
接下來我想讨論的是存在繼承關系時,析構函數在做些什麼?      

派生類對象的析構過程:

1,調用派生類對象的析構函數,      
2,調用派生類中成員對象的析構函數      
3,調用基類的析構函數      
再說c++虛析構函數
-------------------------------------我是醜陋的分割線-------------------------------------------      
在分割線的上方,一切正常,沒有什麼特别的,異樣的地方。      
接下來要讨論的是多态情況下的析構函數。      
#include <iostream>      
using namespace std;      
#include <string>      
class Student      
{      
public:      
Student()      
{      
name = new char[32];      
cout << "Student constructor new name char[32]" << endl;      
}      
~Student()      
{      
delete []name;      
cout << "Student destructor delete Student::name" << endl;      
}      
private:      
char* name;      
};      
class Base      
{      
public:      
Base()      
{      
cout << "Base()" << endl;      
}      
~Base()      
{      
cout << "~Base()" << endl;      
}      
};      
class Derived:public Base      
{      
public:      
Derived()      
{      
cout << "Derived()" << endl;      
}      
~Derived()      
{      
cout << "~Derived()" << endl;      
}      
Student stu;      
};      
int main()      
{      
Base* pb = new Derived(); // 注意這一行,基類指針指向了派生類      
delete pb;  	      // delete 基類指針      
return 0;      
}      
執行結果:      
再說c++虛析構函數
再說c++虛析構函數
隻調用基類的析構函數,派生類的析構函數沒有被調用,更要注意的是,是以派生類的成員對象也沒有被析構,缺少了“Student destructor delete Student::name”      
是以會有記憶體洩漏。      
如下代碼也會出現記憶體洩漏:      
class Base      
{      
};      
class Derived:public Base      
{      
public:      
string str; // 這種記憶體洩漏就不容易發現了!!!      
};      
int main()      
{      
Base* pb = new Derived(); // 派生類的string對象會發生記憶體洩漏!      
delete pb;      
return 0;      
}      
如上類繼承時發生的記憶體洩漏,如何解決?      
隻需要将基類的析構函數聲明為虛析構函數,就是前面加上virtual.      
#include <iostream>      
using namespace std;      
#include <string>      
class Student      
{      
public:      
Student()      
{      
name = new char[32];      
cout << "Student constructor new name char[32]" << endl;      
}      
~Student()      
{      
delete []name;      
cout << "Student destructor delete Student::name" << endl;      
}      
private:      
char* name;      
};      
class Base      
{      
public:      
Base()      
{      
cout << "Base()" << endl;      
}      
virtual ~Base()      
{      
cout << "~Base()" << endl;      
}      
};      
class Derived:public Base      
{      
public:      
Derived()      
{      
cout << "Derived()" << endl;      
}      
~Derived()      
{      
cout << "~Derived()" << endl;      
}      
Student stu;      
};      
int main()      
{      
Base* pb = new Derived();      
delete pb;      
return 0;      
}      
再說c++虛析構函數
運作結果:
發現一切OK了。
總結:      
1.所有基類的析構函數,都應該聲明為虛析構函數!這也是c++标準所指定的。      
2.如果設計一個類,可能會被後來的其他類所繼承,我們一定要将它的析構函數聲明為虛析構。否則被繼承會出現記憶體洩漏等意想不到的問題。      
3.如果我們要去繼承另外一個類,首先一點是要保證被繼承的類的析構函數已經聲明為了虛析構函數!      

繼續閱讀