(C++)淺談多態基類析構函數聲明為虛函數


主要內容:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM