主要內容:
1、C++類繼承中的構造函數和析構函數
2、C++多態性中的靜態綁定和動態綁定
3、C++多態性中析構函數聲明為虛函數
1、C++類繼承中的構造函數和析構函數
在C++的類繼承中,
建立對象時,首先調用基類的構造函數,然后在調用下一個派生類的構造函數,依次類推;
析構對象時,其順序正好與構造相反;
具體參考文章:http://www.cnblogs.com/AndyJee/p/4575385.html
2、C++多態性中的靜態綁定和動態綁定
對象的靜態類型:對象在聲明是采用的類型,在編譯期確定;
對象的動態類型:當前對象所指的類型,在運行期決定,對象的動態類型可以更改,但靜態類型無法更改。
靜態綁定:綁定的是對象的靜態類型,某特性(比如函數)依賴於對象的靜態類型,發生在編譯期。
動態綁定:綁定的是對象的動態類型,某特性(比如函數)依賴於對象的動態類型,發生在運行期。
具體參考文章:http://www.cnblogs.com/AndyJee/p/4575670.html
3、C++多態性中基類析構函數聲明為虛函數
先來看幾段程序例子:
- 將基類析構函數聲明為虛函數
#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 to base class Student *pt4 = new Student; delete pt1; cout << "*********" << endl; delete pt2; cout << "*********" << endl; //delete pt3; //cout << "*********" << endl; delete pt4; cout << "*********" << endl; return 0; }
運行結果:
- 不將基類析構函數聲明為虛函數:
#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 to base 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,會調用靜態類型即基類的析構函數,而不會調用派生類的析構函數。
(以上純屬個人理解)
總結:
-
應該為多態基類聲明虛析構器。一旦一個類包含虛函數,它就應該包含一個虛析構器,因為多態性,必定會有基類調用派生類。
-
如果一個類不用作基類或者不需具有多態性,便不應該為它聲明虛析構器。
參考文章:
http://www.cnblogs.com/children/archive/2012/08/13/2636956.html