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

c++語言中虛函數(shù)實(shí)現(xiàn)多態(tài)的原理詳解

 更新時(shí)間:2019年05月28日 08:26:12   作者:coding小菜鳥  
這篇文章主要給大家介紹了關(guān)于c++語言中虛函數(shù)實(shí)現(xiàn)多態(tài)的原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c++語言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

自上一個(gè)帖子之間跳過了一篇總結(jié)性的帖子,之后再發(fā),今天主要研究了c++語言當(dāng)中虛函數(shù)對(duì)多態(tài)的實(shí)現(xiàn),感嘆于c++設(shè)計(jì)者的精妙絕倫

c++中虛函數(shù)表的作用主要是實(shí)現(xiàn)了多態(tài)的機(jī)制。首先先解釋一下多態(tài)的概念,多態(tài)是c++的特點(diǎn)之一,關(guān)于多態(tài),簡而言之就是 用父類的指針指向其子類的實(shí)例,然后通過父類的指針調(diào)用實(shí)際子類的成員函數(shù),這種方法呢,可以讓父類的指針具有多種形態(tài),也就是說不需要改動(dòng)很多的代碼就可以讓父類這一種指針,干一些很多子類指針的事情,這里是從虛函數(shù)的實(shí)現(xiàn)機(jī)制層面進(jìn)行研究

在寫這篇帖子之前對(duì)于相關(guān)的文章進(jìn)行了查閱,基本上是大段的文字,所以我的這一篇可能會(huì)用大量的圖形進(jìn)行贅述(如果理解有誤的地方,煩請(qǐng)大佬能夠指出),接下來就言歸正傳:

首先介紹一下為什么會(huì)引進(jìn)多態(tài)呢,基于c++的復(fù)用性和拓展性而言,同類的程序模塊進(jìn)行大量重復(fù),是一件無法容忍的事情,比如我設(shè)置了蘋果,香蕉,西瓜類,現(xiàn)在想把這些東西都裝到碗這個(gè)函數(shù)里,那么在主函數(shù)當(dāng)中,聲明對(duì)象是必須的,但是每一次裝進(jìn)碗里對(duì)于水果來說,都要用自己的指針調(diào)用一次裝的功能,那為什么不把這些類抽象成一個(gè)水果類呢,直接定義一個(gè)水果類的指針一次性調(diào)用所有水果裝的功能呢,這個(gè)就是利用父類指針去調(diào)用子類成員,但是這個(gè)思想受到了指針指向類型的限制,也就是說表面指針指向了子類成員,但實(shí)際上還是只能調(diào)用子類成員里的父類成員,這樣的思想就變的毫無意義了,如果想要解決這個(gè)問題,只要在父類前加上virtual就可以解決了,這里就是利用虛函數(shù)實(shí)現(xiàn)多態(tài)的實(shí)例。

首先還是作為舉例來兩個(gè)類,在之前基礎(chǔ)知識(shí)的帖子中提到過,空類的大小是一個(gè)字節(jié)(占位符),函數(shù),靜態(tài)變量都在編譯期就形成了,不用類去分配空間,但是做一個(gè)小實(shí)驗(yàn),看一看在定義了虛函數(shù)之后,類的大小是多少呢

#include<iostream>
using namespace std;
class CFather 
{
public:
  virtual void AA()  //虛函數(shù)標(biāo)識(shí)符
  {
    cout << "CFather :: AA()" << endl;
  }
  void BB()
  {
    cout << "CFather :: BB()" << endl;
  }
};
class CSon : public CFather
{
public:
  void AA()
  {
    cout << "CSon :: AA()" << endl;
  }
  void BB()
  {
    cout << "CSon :: BB()" << endl;
  }
};
int main()
{
  cout << sizeof(CFather) << endl;         //測試加了虛函數(shù)的類

  system("pause");
  return 0;
}

很明顯類里裝了一個(gè) 4個(gè)字節(jié)的東西,除了整形int,就是指針了,沒錯(cuò)這里裝的就是函數(shù)指針

先把這個(gè)代碼,給抽象成圖形進(jìn)行理解,在這CFather為A,CSon為B

此時(shí)就是一個(gè)單純的繼承的情況,不存在虛函數(shù),然后我new一個(gè)對(duì)象,A *p = new A;那么 p -> AA(),必然是指向A類中的AA()函數(shù),那么函數(shù)的調(diào)用有兩種方式 一種函數(shù)名加()直接調(diào)用,一種是利用函數(shù)指針進(jìn)行調(diào)用,在這里我想要調(diào)用子類的,就可以利用函數(shù)指針進(jìn)行調(diào)用,假設(shè)出來兩個(gè)函數(shù)指針,來指向B類中的兩個(gè)成員函數(shù),如果我父類想要調(diào)用子類成員,就可以通過 p指針去調(diào)用函數(shù)指針,再通過函數(shù)指針去調(diào)用成員函數(shù)

,

每一個(gè)函數(shù)都可以用一個(gè)函數(shù)指針去指著,那么每一類中的函數(shù)指針都可以形成自己的一個(gè)表,這個(gè)就叫做虛函數(shù)表

那么在創(chuàng)建對(duì)象后,為什么類中會(huì)有四個(gè)字節(jié)的內(nèi)存空間呢?

在C++的標(biāo)準(zhǔn)規(guī)格說明書中說到,編譯器必需要保證虛函數(shù)表的指針存在于對(duì)象中最前面的位置(這是為了保證正確取到虛函數(shù)的偏移量)。這意味著我們通過對(duì)象實(shí)例的地址得到這張?zhí)摵瘮?shù)表,然后就可以遍歷其中函數(shù)指針,并調(diào)用相應(yīng)的函數(shù)。也就是說這四個(gè)字節(jié)的指針,代替了上圖中(p->*pfn)()的作用,指向了函數(shù)指針,也就是說,在使用了虛函數(shù)的父類成員函數(shù),雖然寫的還是p->AA(),實(shí)際上卻是,(p->*(vfptr[0])),而指向哪個(gè)虛函數(shù)表就由,創(chuàng)建的對(duì)象來決定

至此,就能理解如何用虛函數(shù)這個(gè)機(jī)制來實(shí)現(xiàn)多態(tài)的了

下面,我將分別說明“無覆蓋”和“有覆蓋”時(shí)的虛函數(shù)表的樣子。沒有覆蓋父類的虛函數(shù)是毫無意義的。我之所以要講述沒有覆蓋的情況,主要目的是為了給一個(gè)對(duì)比。在比較之下,我們可以更加清楚地知道其內(nèi)部的具體實(shí)現(xiàn)。

無虛數(shù)覆蓋

下面,再讓我們來看看繼承時(shí)的虛函數(shù)表是什么樣的。假設(shè)有如下所示的一個(gè)繼承關(guān)系:

請(qǐng)注意,在這個(gè)繼承關(guān)系中,子類沒有重載任何父類的函數(shù)。那么,在派生類的實(shí)例中,Derive d; 的虛函表:

我們可以看到下面幾點(diǎn):

1)虛函數(shù)按照其聲明順序放于表中。

2)父類的虛函數(shù)在子類的虛函數(shù)前面。

有虛數(shù)覆蓋

覆蓋父類的虛函數(shù)是很顯然的事情,不然,虛函數(shù)就變得毫無意義。下面,我們來看一下,如果子類中有虛函數(shù)重載了父類的虛函數(shù),會(huì)是一個(gè)什么樣子?假設(shè),我們有下面這樣的一個(gè)繼承關(guān)系。

為了讓大家看到被繼承過后的效果,在這個(gè)類的設(shè)計(jì)中,我只覆蓋了父類的一個(gè)函數(shù):f()。那么,對(duì)于派生類的實(shí)例,其虛函數(shù)表會(huì)是下面的一個(gè)樣子:

我們從表中可以看到下面幾點(diǎn),

1)覆蓋的f()函數(shù)被放到了虛表中原來父類虛函數(shù)的位置。

2)沒有被覆蓋的函數(shù)依舊。

這樣,我們就可以看到對(duì)于下面這樣的程序,

Base *b = new Derive();

b->f();

由b所指的內(nèi)存中的虛函數(shù)表的f()的位置已經(jīng)被Derive::f()函數(shù)地址所取代,于是在實(shí)際調(diào)用發(fā)生時(shí),是Derive::f()被調(diào)用了。這就實(shí)現(xiàn)了多態(tài)。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • linux c 查找使用庫的cflags與libs的方法詳解

    linux c 查找使用庫的cflags與libs的方法詳解

    本篇文章是對(duì)在linux中使用c語言查找使用庫的cflags與libs的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • CMake語法及CMakeList.txt簡單使用小結(jié)

    CMake語法及CMakeList.txt簡單使用小結(jié)

    Cmake主要用于開發(fā)跨平臺(tái)的C++項(xiàng)目,本文主要介紹了CMake語法及CMakeList.txt簡單使用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-05-05
  • VsCode安裝和配置c/c++環(huán)境小白教程(圖文)

    VsCode安裝和配置c/c++環(huán)境小白教程(圖文)

    本文主要介紹了VsCode安裝和配置c/c++環(huán)境小白教程,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C++內(nèi)存泄漏的檢測與實(shí)現(xiàn)詳細(xì)流程

    C++內(nèi)存泄漏的檢測與實(shí)現(xiàn)詳細(xì)流程

    內(nèi)存泄漏(memory leak) 是指由于疏忽或錯(cuò)誤造成了程序未能釋放掉不再使用的內(nèi)存的情況。內(nèi)存泄漏并非指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,由于設(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)
    2022-08-08
  • 關(guān)于C++中的static關(guān)鍵字的總結(jié)

    關(guān)于C++中的static關(guān)鍵字的總結(jié)

    C++的static有兩種用法:面向過程程序設(shè)計(jì)中的static和面向?qū)ο蟪绦蛟O(shè)計(jì)中的static。前者應(yīng)用于普通變量和函數(shù),不涉及類;后者主要說明static在類中的作用
    2013-09-09
  • C++面向?qū)ο笳Z言自制多級(jí)菜單功能實(shí)現(xiàn)代碼

    C++面向?qū)ο笳Z言自制多級(jí)菜單功能實(shí)現(xiàn)代碼

    菜單類主要負(fù)責(zé)菜單的創(chuàng)建、修改、刪除,是包含菜單結(jié)構(gòu)組織和響應(yīng)函數(shù)的模型,用戶擁有充分的自主性,可根據(jù)需要自定義菜單顯示和響應(yīng)函數(shù),這篇文章主要介紹了C++面向?qū)ο笳Z言自制多級(jí)菜單,需要的朋友可以參考下
    2024-06-06
  • C++ xxx_cast實(shí)現(xiàn)轉(zhuǎn)換代碼實(shí)例解析

    C++ xxx_cast實(shí)現(xiàn)轉(zhuǎn)換代碼實(shí)例解析

    這篇文章主要介紹了C++xxx_cast轉(zhuǎn)換代碼實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • C++ opencv圖像處理實(shí)現(xiàn)圖片幾何變換示例

    C++ opencv圖像處理實(shí)現(xiàn)圖片幾何變換示例

    這篇文章主要為大家介紹了C++ opencv圖像處理實(shí)現(xiàn)圖片幾何變換示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • C++ 讀取文件內(nèi)容到指定類型的變量方法

    C++ 讀取文件內(nèi)容到指定類型的變量方法

    今天小編就為大家分享一篇C++ 讀取文件內(nèi)容到指定類型的變量方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • c++智能指針的超詳細(xì)講解

    c++智能指針的超詳細(xì)講解

    c++程序設(shè)計(jì)中經(jīng)常會(huì)用堆內(nèi)存,程序員要自己管理內(nèi)存的申請(qǐng)和釋放,使用原始指針,容易造成堆內(nèi)存泄漏(忘記釋放),二次釋放,使用智能指針能更好的管理堆內(nèi)存,下面這篇文章主要給大家介紹了關(guān)于c++智能指針的相關(guān)資料,需要的朋友可以參考下
    2022-06-06

最新評(píng)論

东宁县| 平乐县| 锡林浩特市| 安仁县| 丰宁| 皮山县| 石河子市| 河西区| 柳河县| 天镇县| 宜川县| 尉氏县| 偃师市| 莆田市| 嘉祥县| 丘北县| 弥勒县| 乌拉特后旗| 南开区| 吉水县| 福海县| 潢川县| 玛沁县| 苍南县| 万宁市| 鄂温| 连江县| 芷江| 额尔古纳市| 聂拉木县| 容城县| 姜堰市| 广州市| 会理县| 鄂温| 桦甸市| 辽阳市| 九龙坡区| 赫章县| 武隆县| 遂溪县|