天天看點

淺談多态基類析構函數聲明為虛函數

為什麼基類的析構函數需要聲明為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