淺談多態基類析構函數聲明爲虛函數

爲什麼基類的析構函數需要聲明爲virtual??

主要內容:

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++多態性中基類析構函數聲明爲虛函數

先來看幾段程序例子:

  • 將基類析構函數聲明爲虛函數

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

#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;

}

運行結果:

  • 不將基類析構函數聲明爲虛函數:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

#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,會調用靜態類型即基類的析構函數,而不會調用派生類的析構函數。

(以上純屬個人理解)

 

總結:

  • 應該爲多態基類聲明虛析構器。一旦一個類包含虛函數,它就應該包含一個虛析構器,因爲多態性,必定會有基類調用派生類。

  • 如果一個類不用作基類或者不需具有多態性,便不應該爲它聲明虛析構器。

轉自:

https://www.cnblogs.com/AndyJee/p/4575810.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章