1. 程式人生 > >(轉載)(C++)淺談多型基類解構函式宣告為虛擬函式

(轉載)(C++)淺談多型基類解構函式宣告為虛擬函式

主要內容:

1、C++類繼承中的建構函式和解構函式

2、C++多型性中的靜態繫結和動態繫結

3、C++多型性中解構函式宣告為虛擬函式

1、C++類繼承中的建構函式和解構函式
在C++的類繼承中,

建立物件時,首先呼叫基類的建構函式,然後在呼叫下一個派生類的建構函式,依次類推;

析構物件時,其順序正好與構造相反;

2、C++多型性中的靜態繫結和動態繫結
物件的靜態型別:物件在宣告是採用的型別,在編譯期確定;

物件的動態型別:當前物件所指的型別,在執行期決定,物件的動態型別可以更改,但靜態型別無法更改。

靜態繫結:繫結的是物件的靜態型別,某特性(比如函式)依賴於物件的靜態型別,發生在編譯期。
動態繫結:繫結的是物件的動態型別,某特性(比如函式)依賴於物件的動態型別,發生在執行期。

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

執行結果:
結果 1

不將基類解構函式宣告為虛擬函式:

#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,會呼叫靜態型別即基類的解構函式,而不會呼叫派生類的解構函式。

(以上純屬個人理解)

總結:
應該為多型基類宣告虛析構器。一旦一個類包含虛擬函式,它就應該包含一個虛析構器,因為多型性,必定會有基類呼叫派生類。

如果一個類不用作基類或者不需具有多型性,便不應該為它宣告虛析構器。

參考文章:

相關推薦

轉載C++函式宣告虛擬函式

主要內容: 1、C++類繼承中的建構函式和解構函式 2、C++多型性中的靜態繫結和動態繫結 3、C++多型性中解構函式宣告為虛擬函式 1、C++類繼承中的建構函式和解構函式 在C++的類繼承中, 建立物件時,首先呼叫基類的建構函式,然後在呼叫下一

C++函式宣告虛擬函式

主要內容: 1、C++類繼承中的建構函式和解構函式 2、C++多型性中的靜態繫結和動態繫結 3、C++多型性中解構函式宣告為虛擬函式 1、C++類繼承中的建構函式和解構函式 在C++的類繼承中, 建立物件時,首先呼叫基類的建構函式,然後在呼叫下一個派生類的建構函式,依次類推; 析構物件時,其

C++函式宣告虛擬函式

先來看幾段程式例子:1. 將基類解構函式宣告為虛擬函式#include <iostream

函式必須虛擬函式否則會造成記憶體洩漏

看看下面程式有什麼錯誤: #include <iostream> using namespace std; class Father { public: Father(){}; ~Father(){}; }; class Son:public

C#學習——介面、抽象、介面繼承、繼承

引言:  學習面嚮物件語言有一陣子了,聽也聽的多了,但是真正用起來的時候,還是有些陌生,這個Iworkspace,那個IworkspaceFactory還有次一級的很多,雖然我能夠知道他們之間的關係,但是在應用的時候就有點迷了,所以想梳理一下。 首先這塊內容,比如介面和抽象類

中的虛擬函式和虛表

需要實現多型必不可少的就是虛擬函式,類的成員函式前加virtual關鍵字,這個成員函式就是虛擬函式;例如: class T { public: virtual void fun() { cout<<"fun()"<<endl; }

以及php的實現方法

先簡單說一下多型 多型的三大特徵: 子類繼承父類 子類重寫父類 父類指向子類 多型實現的前提:必須是類與類之間要有關係,要麼繼承,要麼實現,存在重寫(override),其實就是抽象函式或介面。 多型的應用:父類物件的引用指向子類物件,其實本質上就是

C++函式中那些不可以被宣告虛擬函式函式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Effective C++筆記之七:宣告virtual函式

應該為多型基類宣告virtual解構函式,否則容易造成記憶體洩露。 因為C++明白指出,當derived class物件經由一個base class指標被刪除,而該base class如果帶有一個non-virtual解構函式,其結果未定義一實際執行時通常發生的是物件的derived成分沒

effective c++乾貨之條款07:宣告virtual函式

1. 避免記憶體洩漏 首先,我們實現一個多型: class CPeople { public: CPeople(){} virtual ~CPeople(){} }; class CChinese:public CPeople { public:

讀書筆記《Effective c++》 條款07 宣告virtual函式

這個其實不用多說,用過OO類的語言應該都要這樣。 這麼看來簡單的物件和delphi的物件結構差不多。 書中說c++不支援final,在c++11中已經支援了,所以如果不希望類被繼承,可以加上final c++的final有兩個用途: 1.阻止類被繼承 2.組織虛擬函式被

C++及虛函式

C++實現多型 多型:支援相關的物件具有不同的成員函式(但原型相同) ,並允許物件與適當的成員函式進行執行時繫結。 虛表和虛表指標介紹 當呼叫一個虛擬函式時,被執行的程式碼必須與

C/C++語法二十三種設計模式——工廠模式Factory Method

0.寫在前面 在軟體開發過程中,為了提高開發效率、增強軟體執行的穩定性,降低後期專案維護的成本,我們志在追求更加高效、簡單的設計思路來引領我們的專案產品,在經過不斷的探索與總結的過程中,我們最常用的設計模式有23中,總體分為三大類,即建立型模式、結構型模式和行為型模式,具體如下:

C/C++語法六大設計原則——依賴倒置原則Dependence Inversion Principle

一. 前言 眾所周知,在軟體開發過程中,我們的六大設計原則與二十三種設計模式可以說是我們開發的思想精髓。然而,網上或者書本大多數的資料都是以java、python等其他語言語法進行介紹與闡述,很少有以C/C++的語法進行深入介紹。鑑於此,本人以淺薄的見識對這些精妙的思想做以總結,方便

python學習-09查找、排序和數據結構

使用 指定 矩陣 這樣的 重復 n) init enc nbsp 查找的方法: 排序的方法: 簡單的數據結構: 一、算計基礎 1.1、什麽是算法: 算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,算法代表著用系統的方法描述解決問題的策略

運維角度MySQL數據庫優化

臨時 keyword 由於 數據查詢 apr database inno 兩臺 麻煩    轉自:http://lizhenliang.blog.51cto.com/7876557/1657465 一個成熟的數據庫架構並不是一開始設計就具備高可用、高伸縮等特性的,它是隨著用

libgo 原始碼剖析1. libgo簡介與排程

閒談 協程是一個很早的概念了,早些年的遊戲行業中已經大規模地在使用,像lua、go這些語言中的協程原語已經相對比較完善了,一般來說直接使用就好,但是在系統後臺開發上,出現的時間並不長。我是做C++方向的後臺開發,目前國內一些公司也開源了一些C++協程庫,但目前來說,還是在逐步完善的階段。最早接觸的C++協程

(轉載) Objective-C程式碼混淆轉載自念茜

class-dump可以很方便的匯出程式標頭檔案,不僅讓攻擊者瞭解了程式結構方便逆向,還讓著急趕進度時寫出的欠完善的程式給同行留下笑柄。 所以,我們迫切的希望混淆自己的程式碼。 混淆的常規思路 混淆分許多思路,比如: 1)花程式碼花指令,即隨意往程式中加入迷惑人的

電路設計與PCB布板含MSP430程式除錯經驗

上週調了一個電路板,結合到之前畫過的一塊板子,現在寫一點點心得,留作日後自我取笑解嘲。 首先,原理圖設計。 這玩意兒難得沒有百密一疏的時候,所以很少一次性投板後就不用改了的時候。一般參照datasheet的電路。一般常見的電路也可上網搜尋,一大把。但是一定要知道這些電阻電容

springboot學習總結Spring security原理

學習 security uwp manage adg aac dsi sin aci 認證是由 AuthenticationManager 來管理的,但是真正進行認證的是 AuthenticationManager 中定義的 AuthenticationProvider。A