91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++中可以通過指針或引用實現多態的原因是什么

發布時間:2021-04-06 09:34:41 來源:億速云 閱讀:414 作者:小新 欄目:開發技術

這篇文章主要介紹c++中可以通過指針或引用實現多態的原因是什么,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

引言:

在c++中司空見慣的事情就是:可以通過指針和引用可以實現多態,而對象不可以。 那為什么?讓我們來解開這神秘的暗紗!

1、 類對象的存儲方式:

在一個類的實例中,只會存放非靜態的成員變量。 如果該類中存在虛函數的話,再多加一個指向虛函數列表指針—vptr。

例如聲明如下兩個類,并分別實例化兩個對象,它們的內存分配大致如下:(vptr具體在什么位置,與編譯器有關,大多數都在開始處)

class base
{
public:
 virtual ~base() {};
 virtual string GetName() { return "base"; }
 GetA();
 int a;
};

class derived : public base
{
public:
 virtual ~derived() {};
 virtual string GetName() { return "derived";}
 GetB();
 int b;
};base B1, B2;derived D1, D2;

內存分布大致如下:

1. 類對象中,只有成員變量與vptr.

2. 普通成員函數在內存的某一位置放著。它們與c語言中定義的普通函數沒有區別。 當我們通過對象或對象指針調用普通成員函數時, 編譯器會拿到它。怎么拿到呢?當然是通過名字了,編譯器都會對我們寫的函數的名字進行修飾映射,讓它們變成內存中唯一的函數名。

3. 無論基類還是子類,每一種類類型的虛函數表只有一份,它里面存放了基類的類型信息和指向基類中的虛函數的指針。 某一類類型的所有對象都指向了相同的虛函數表。

c++中可以通過指針或引用實現多態的原因是什么

2. 無論通過對象還是指針,能使用的方法只與它們靜態類型有關。

例如:下面的 base類型的對象B1或指針pB1,只能使用GetName() 和GetA()方法。 無論它們是如何來的!!!!!

// 直接構造得到
base B1;
base* pB1 = new base();

// 即使從子類轉換而來, 通過B1或pB1也永遠訪問不到GetB()方法。
derived d1;
B1 = d1;
pB1 = new derived();

3. 不同類型的指針有什么區別?

本質上它們沒有任何區別,在32/64位系統中都是4/8字節的一個變量。 唯一不同的就是編譯器解釋它們的方式,即通過指針來尋址出來的對象類型不同,大小不同 ,指針類型來告訴編譯器如何解釋該指針。

4. 指針與引用來實現多態

有代碼如下 :

derived* _pD = new derived();
base* _pB = _pD;
_pB.GetName(); // 返回 derived.

想要知道如何通過指針來實現的多態,就要看看對基類指針賦值是發生了什么! 具體來說 如下圖所示:

c++中可以通過指針或引用實現多態的原因是什么

我們會發現,對指針的賦值,僅僅是讓基類指針_pB指向的子類對象的地地址。 當我們使用基類指針調用GetName()函數(該函數是虛函數,它的地址在函數表中)時, 會由_pB指向的地址找到子類的虛函數表指針vptr_上海,再由vptr_上海在虛函數表中找到子類的GetName(),從而調用它。就這樣實現了多態。

5. 對象不能實現多態

有代碼如下:

base B1;
derived D1;
B1 = D1;
B1.GetName();  // 返回 base

base B2 = D1
B2.GetName(); // 返回 base

上面代碼中無論賦值操作還是賦值構造時, 只會處理成員變量,一個類對象里面的vptr永遠不會變,永遠都會指向所屬類型的虛函數表,操作如下圖所示:

c++中可以通過指針或引用實現多態的原因是什么

因此,通過對象調用虛函數時,就沒有必要進行動態解析了,白白增加了間接性,浪費性能。編譯器直接在編譯時就可以確認具體調用哪一個函數了,因此沒有所謂的多態。

補充說明:

1. 引用本質上也是通過指針的解引用(即*_point)來實現的,可以<<參考std源碼剖析》一本書,所以引用也可以實現多態。

2. 即使通過 基類的指針調用基類的虛函數 或 通過子類的指針調用子類的虛函數 以及通過子類指針調用基類的虛函數, 也是通過多態機制來完成的(即一步步的間接性來完成)。

3. 一個空的class的對象的大小為1個字節, 編譯器之所以要這么做,是為了區別同一個類類型的不同對象!

以上是“c++中可以通過指針或引用實現多態的原因是什么”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

恭城| 余姚市| 迭部县| 海门市| 怀仁县| 晋江市| 靖江市| 社旗县| 灵武市| 古浪县| 洪雅县| 顺义区| 郧西县| 札达县| 扎鲁特旗| 白朗县| 肃北| 聂拉木县| 大丰市| 获嘉县| 扎囊县| 乐亭县| 瑞金市| 蓝山县| 信阳市| 宜君县| 岑巩县| 崇州市| 孝昌县| 嘉荫县| 武清区| 张北县| 宝鸡市| 隆子县| 开封县| 阜平县| 台江县| 新安县| 深泽县| 英山县| 城市|