1. 程式人生 > >建構函式及解構函式與虛擬函式的關係

建構函式及解構函式與虛擬函式的關係

我們都知道建構函式不能為虛擬函式,而基類的解構函式一般都要定義為虛擬函式。今天重新複習了一下,特在此記載,以便查詢。

建構函式不能為虛擬函式主要有以下兩點

1、必要性分析:
當定義派生類物件時,它會主動依次呼叫建構函式,順序為基類的建構函式->一級派生類建構函式->二級派生類建構函式….直到當前派生類的建構函式呼叫完畢為止,到此派生類物件生成。
而虛擬函式存在的意義為動態繫結,從上一段話可知,它會從基類開始依次自動呼叫相應的建構函式,根本就不存在動態繫結的必要。
2、記憶體角度分析:
建構函式的作用是生成相應的類物件。虛擬函式的動態繫結是依據一張虛擬函式表來確認的最終繫結到哪一個虛擬函式版本。
而呼叫建構函式之前,我們對類物件所做的操作僅限於分配記憶體,還沒有對記憶體進行初始化。此時,記憶體空間上也不存在虛擬函式表,因此,按照這樣的執行順序,虛擬函式的動態繫結是實現不了的。

基類解構函式與虛擬函式的關係

如果類的資料成員中不存在成員(指標)與動態分配的記憶體相關聯,我們一般不用自己定義解構函式,而是採用預設的解構函式析構類物件。一旦與動態分配的記憶體相關聯,為了防止記憶體洩露,我們需要自己定義解構函式,手動釋放動態分配的記憶體。

三法則:如果一個類需要解構函式,幾乎也需要定義賦值建構函式和過載賦值操作符。

在分析基類解構函式為什麼要定義為虛解構函式之前,我們要先明白虛擬函式存在的意義就是為了動態繫結,實現面向物件的特性之一 :多型。

我們知道通過基類的指標或者引用可以實現對虛擬函式的動態繫結,那麼當我們通過一個基類指標或者引用來析構一個物件時,我們是無法判斷基類現在繫結的物件是基類還是派生類,如果解構函式不是虛擬函式,那麼基類指標只會呼叫基類的解構函式,如此就發生了一些不該發生的事。只有將解構函式定義為虛擬函式,才能通過動態繫結,呼叫對應的解構函式版本,正確的析構類物件。

可以這麼說:任何class只要有virtual函式都幾乎確定也要有一個virtual解構函式(引用自Effective C++ 條款7)

相關推薦

建構函式函式虛擬函式關係

我們都知道建構函式不能為虛擬函式,而基類的解構函式一般都要定義為虛擬函式。今天重新複習了一下,特在此記載,以便查詢。 建構函式不能為虛擬函式主要有以下兩點 1、必要性分析: 當定義派生類物件時,它會主動依次呼叫建構函式,順序為基類的建構函式->一

建構函式函式

建構函式及解構函式是一組特殊的成員函式,用來對物件進行初始化以及回收,這兩個都是與例項物件掛鉤的,當該類被例項物件化時,建構函式就會自動執行,當該類結束時,就會自動進行解構函式,可以說例項物件是以建構函式開始,以解構函式為結束。 建構函式的定義規範是具有與該類相同的名稱,例如程式: na

對C++中建構函式函式虛擬函式普通成員函式的理解

這裡我們主要討論建構函式、解構函式、普通成員函式、虛擬函式,對這幾種函式說說自己的理解。 對建構函式的總結 對建構函式,我們先來看看如下的程式碼 #include <iostream> using namespace std; cla

虛擬函式實現機制、建構函式函式能否為虛擬函式虛擬函式

 虛擬函式 虛擬函式是C++中用於實現多型的機制。核心理念就是通過基類指標訪問派生類中定義的函式。虛擬函式允許子類重新定義成員函式,繼承時不重新定義虛擬函式也是可以的。而子類重新定義父類的做法稱為覆蓋(override),或者稱為重寫。如果父類或者祖先類中函式func()為虛

派生類的建構函式和解函式和多繼承中的二義性虛擬函式

解構函式主要作用是對資料成員初始化。 1派生類的建構函式 派生類的建構函式定義的一般形式為: 派生類名::派生類名(基類所需形參,本類成員所需形參):基類1(基類1 引數表),基類2(基類2 引數表),···,基類n(基類n 引數表),物件成員1(物件1 引數表),物件成員2(物件2 引

基類函式虛擬函式

    基類解構函式為什麼要宣告為虛擬函式?     這個問題是C++理解虛擬函式和動態繫結的一個基礎,也是面試常考的一個點。雖然幾乎每本書中都會提及這個點,但是很少有把其具體闡明。本文通過具體例項+理論闡述儘量清晰解釋這個問題。

從零開始學C++之虛擬函式多型(一):虛擬函式表指標、虛函式、object slicing虛擬函式、C++物件模型圖

#include <iostream>using namespace std;class CObject {public:     virtual void Serialize()     {         cout << "CObject::Serialize ..." <&

C++ 建構函式函式中能否呼叫虛擬函式

牛客網 ------------------- ------------------- ------------------- 設計模式 ------------------- -------------------

C++建構函式函式虛擬函式

建構函式 1.建立物件時會依次呼叫基類和子類的建構函式,各個建構函式負責對自己類中定義的成員的初始化工作。 2.如果使用者不宣告任何建構函式,編譯器將提供一個預設建構函式(default constructor),只要使用者定義了自己的建構函式,不論包不包括預設建構函式,編

為什麼建構函式不能宣告為虛擬函式函式可以

1. 如果我們定義了一個建構函式,編譯器就不會再為我們生成預設構造函數了。2. 編譯器生成的解構函式是非虛的,除非是一個子類,其父類有個虛析構,此時的函式虛特性來自父類。3. 有虛擬函式的類,幾乎可以確定要有個虛解構函式。4. 如果一個類不可能是基類就不要申明解構函式為虛擬函式,虛擬函式是要耗費空間的。5.

C++之函式虛擬函式

一個例子 class Base { public: Base() { } ~Base() { cout << "Base 析構" << endl; } }; class D

函式為什麼不能宣告為虛擬函式函式為什麼要宣告為虛擬函式

多型中的虛擬函式表是在執行時建立的還是編譯時建立的? 答:虛擬函式表在編譯的時候就確定了,而類物件的虛擬函式指標vptr是在執行階段確定的,這是實現多型的關鍵 (類的函式的呼叫並不是在編譯時就確定的,而是在執行時才確定的,由於編寫程式碼的時候並不能確定被呼叫的是基類的函式還是哪個派生類的函式,所以宣告為虛

找工作筆試面試那些事兒(5)---建構函式函式和賦值函式

作者:寒小陽 時間:2013年9月。 出處:http://blog.csdn.net/han_xiaoyang/article/details/10833931。 宣告:版權所有,轉載請註明出處,謝謝。 類的建構函式、解構函式與賦值函式     &

建構函式,拷貝建構函式函式,賦值函式

例一: class CGoods {     //行為,成員方法 public:     CGoods(char *name = NULL, int amount = 0, double price = 0.0) //建構函式 &nbs

請為CMyString型別編寫建構函式、copy建構函式函式和賦值運算子函式

如下為型別CMyString的宣告,請為該型別編寫建構函式、copy建構函式、解構函式和賦值運算子函式。 1 class CMyString 2 { 3 public: 4 CMyString(const char* pData = nullptr); 5 CMyS

類和物件——建構函式函式、複製建構函式

類: 要宣告類,用class,注意區分大小寫。類含有成員屬性和方法。在宣告類的末尾要加分號; 物件: 宣告完類之後,它並不能對程式產生任何影響。只有依據類,例項化物件,才可以訪問類成員屬性和方法。 下面是類例項化物件、動態分配記憶體與變數的對比: double pi=3.14; int* p

【C++筆記】編寫類string的建構函式函式和賦值函式

#include<iostream> using namespace std; class String { public: String(const char *str=NULL); //普通建構函式 String(const Stri

類的建構函式函式、拷貝建構函式、賦值函式

 類的四種基本預設函式:建構函式、解構函式、拷貝建構函式、賦值函式。 建構函式:建立類時,系統自動呼叫建構函式,用以初始化,分配空間,沒有自定義的建構函式時,系統預設一個無引數的建構函式。 class book { private:     int isBook;

private建構函式 & 函式

https://www.cnblogs.com/kangyoung/articles/2375211.html   很多情況下要求當前的程式中只有一個object。例如一個程式只有一個和資料庫的連線,只有一個滑鼠的object。通常我們都將建構函式的宣告置於public區段,假如我們將其放入private區

建構函式函式和變數的生存期

//referred from Wei Guo, Peking University #include<iostream> using namespace std; class Demo{ int id; public: Demo(int i)