最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++中為什么可以通過指針或引用實現(xiàn)多態(tài)詳解

 更新時間:2021年04月02日 14:20:44   作者:殷大俠  
這篇文章主要給大家介紹了關(guān)于c++中為何可以通過指針或引用實現(xiàn)多態(tài),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

引言:

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

1、 類對象的存儲方式:

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

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

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;

內(nèi)存分布大致如下:

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

2. 普通成員函數(shù)在內(nèi)存的某一位置放著。它們與c語言中定義的普通函數(shù)沒有區(qū)別。 當(dāng)我們通過對象或?qū)ο笾羔樥{(diào)用普通成員函數(shù)時, 編譯器會拿到它。怎么拿到呢?當(dāng)然是通過名字了,編譯器都會對我們寫的函數(shù)的名字進(jìn)行修飾映射,讓它們變成內(nèi)存中唯一的函數(shù)名。

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

2. 無論通過對象還是指針,能使用的方法只與它們靜態(tài)類型有關(guān)。

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

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

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

3. 不同類型的指針有什么區(qū)別?

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

4. 指針與引用來實現(xiàn)多態(tài)

有代碼如下 :

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

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

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

5. 對象不能實現(xiàn)多態(tài)

有代碼如下:

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

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

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

因此,通過對象調(diào)用虛函數(shù)時,就沒有必要進(jìn)行動態(tài)解析了,白白增加了間接性,浪費性能。編譯器直接在編譯時就可以確認(rèn)具體調(diào)用哪一個函數(shù)了,因此沒有所謂的多態(tài)。

補充說明:

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

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

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

總結(jié)

到此這篇關(guān)于c++中為什么可以通過指針或引用實現(xiàn)多態(tài)的文章就介紹到這了,更多相關(guān)c++指針或引用實現(xiàn)多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于C語言中弱符號與弱引用的實際應(yīng)用問題

    關(guān)于C語言中弱符號與弱引用的實際應(yīng)用問題

    在編碼過程中,我們經(jīng)常遇到符號重定義的錯誤問題,本文通過實例代碼展示給大家介紹了C語言弱符號與弱引用的實際應(yīng)用問題,一起看看吧
    2021-09-09
  • C語言如何計算兩個數(shù)的最小公倍數(shù)

    C語言如何計算兩個數(shù)的最小公倍數(shù)

    這篇文章主要介紹了C語言如何計算兩個數(shù)的最小公倍數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Qt實現(xiàn)輸出日志到指定文件的操作方法

    Qt實現(xiàn)輸出日志到指定文件的操作方法

    這篇文章主要介紹了Qt實現(xiàn)輸出日志到指定文件的操作方法,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • C++ 內(nèi)存分區(qū)模型的使用(代碼區(qū)、全局區(qū)、棧區(qū)、堆區(qū)、new)

    C++ 內(nèi)存分區(qū)模型的使用(代碼區(qū)、全局區(qū)、棧區(qū)、堆區(qū)、new)

    這篇文章主要介紹了C++ 內(nèi)存分區(qū)模型的使用(代碼區(qū)、全局區(qū)、棧區(qū)、堆區(qū)、new),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C++模擬實現(xiàn)vector流程詳解

    C++模擬實現(xiàn)vector流程詳解

    這篇文章主要介紹了C++容器Vector的模擬實現(xiàn),Vector是一個能夠存放任意類型的動態(tài)數(shù)組,有點類似數(shù)組,是一個連續(xù)地址空間,下文更多詳細(xì)內(nèi)容的介紹,需要的小伙伴可以參考一下
    2022-08-08
  • Qt使用QCamera實現(xiàn)切換相機(jī),分辨率和圖像捕獲功能

    Qt使用QCamera實現(xiàn)切換相機(jī),分辨率和圖像捕獲功能

    這篇文章主要為大家介紹了如何利用Qt中的相機(jī)類QCamera,取景器類QCameraViewfinder,圖像捕獲類QCameraImageCapture實現(xiàn)切換相機(jī)、分辨率和圖像捕獲功能,需要的可以了解一下
    2023-04-04
  • C++之a(chǎn)ssert推薦用法及注意事項

    C++之a(chǎn)ssert推薦用法及注意事項

    這篇文章主要給大家介紹了關(guān)于C++之a(chǎn)ssert推薦用法及注意事項的相關(guān)資料,assert 是一個預(yù)處理宏,用于在運行時檢查表達(dá)式是否為真,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • C++編程中的數(shù)據(jù)類型和常量學(xué)習(xí)教程

    C++編程中的數(shù)據(jù)類型和常量學(xué)習(xí)教程

    這篇文章主要介紹了C++編程中的數(shù)據(jù)類型和常量學(xué)習(xí)教程,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C++基于LINUX的文件操作

    C++基于LINUX的文件操作

    這篇文章主要為大家介紹了C++基于LINUX的文件操作示例知識擴(kuò)充,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • OpenCV識別提取圖像中的水平線與垂直線

    OpenCV識別提取圖像中的水平線與垂直線

    這篇文章主要為大家詳細(xì)介紹了OpenCV識別提取圖像中的水平線與垂直線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07

最新評論

讷河市| 江孜县| 昌江| 景谷| 永春县| 西和县| 安康市| 东宁县| 科技| 石林| 许昌县| 内江市| 牙克石市| 石家庄市| 楚雄市| 武邑县| 岳池县| 方山县| 扎兰屯市| 曲沃县| 莱芜市| 永德县| 昌邑市| 佛教| 晋宁县| 泊头市| 阿鲁科尔沁旗| 洪江市| 玉山县| 台南市| 肥东县| 富裕县| 西充县| 怀远县| 乌什县| 宁波市| 浦江县| 宣城市| 辽宁省| 额尔古纳市| 西畴县|