【C++進階】第2課—多態

文章目錄

  • 1. 認識多態
  • 2. 多態的定義和實現
    • 2.1 構成多態的必要條件
    • 2.2 虛函數
    • 2.3 虛函數的重寫或覆蓋
    • 2.4 協變(了解)
    • 2.5 析構函數的重寫
    • 2.6 override和final關鍵字
    • 2.7 重載、重寫、隱藏對比
  • 3. 純虛函數和抽象類
  • 4. 多態原理
    • 4.1 虛函數表指針
    • 4.2 多態的實現
    • 4.3 靜態綁定和動態綁定
    • 4.4 虛函數表

1. 認識多態

  • 通俗點講,多態其實就是多種形態,它分為編譯時多態(靜態多態)和運行時多態(動態多態)
  • 編譯時多態(靜態多態):主要就是之前講過的函數模版和函數重載,它們在編譯階段,通過傳不同類型的參數來調用對應的函數,通過參數不同就可以達到多種形態
  • 運行時多態(動態多態):具體一點就是傳不同對象就可以完成不同的行為(函數),從而達到多種形態。例如:對于買票來說,學生買票半價,普通人全價,軍人優先買票。

2. 多態的定義和實現

  • 多態是一個繼承關系下的類的對象,去調用同一個函數,產生了不同的行為。

在這里插入圖片描述


2.1 構成多態的必要條件

  • 必須是基類的指針或引用調用虛函數
  • 被調用的函數必須是虛函數,并且完成了虛函數的重寫/覆蓋

2.2 虛函數

  • 簡單來說,虛函數就是在類成員函數前面+關鍵字virtual修飾,該成員函數也被稱為虛函數,注意:非成員函數不能+virtual修飾

在這里插入圖片描述


2.3 虛函數的重寫或覆蓋

  • 虛函數的重寫或覆蓋:派生類中有一個跟基類完全相同的虛函數(即返回值、函數名、參數列表類型完全相同),稱為派生類的虛函數重寫了基類的虛函數

在這里插入圖片描述


  • 關于多態,可以看下面三組對比,就明白為啥只有使用基類指針/引用調用虛函數才會實現多態的效果了

在這里插入圖片描述


  • 在重寫虛函數時,派生類的虛函數可以不+virtual,也可以和基類的虛函數構成重寫/覆蓋(基類被繼承后,其虛函數的屬性也被派生類繼承了下來)。但是實際項目中,最好還是加上

在這里插入圖片描述


  • 接下來我們看一道關于多態的選擇題

在這里插入圖片描述


2.4 協變(了解)

  • 派生類重寫虛函數時,與基類虛函數返回值類型不同,即基類虛函數返回基類對象的指針/引用,派生類虛函數返回派生類對象的指針/引用時,稱為協變。實際項目中意義不大,了解即可

在這里插入圖片描述


2.5 析構函數的重寫

  • 基類的析構函數為虛函數,那么派生類的析構函數無論加不加virtual修飾,都和基類的析構函數構成重寫(主要是因為編譯器將類的析構函數名字都特殊處理為destructor)

在這里插入圖片描述


在這里插入圖片描述


2.6 override和final關鍵字

  • 可以看出,C++對于虛函數重寫要求比較高,但也有可能有些情況下就疏忽忘寫,例如函數名寫錯,寫錯參數等,因此C++就提出關鍵字override來檢查是否達到虛函數重寫

在這里插入圖片描述


  • 如果不想讓派生類去重寫虛函數,可用final修飾

在這里插入圖片描述


2.7 重載、重寫、隱藏對比

在這里插入圖片描述


3. 純虛函數和抽象類

  • 在虛函數的后面寫上=0,則這個函數為純虛函數,純虛函數不需要定義實現(實現也沒啥意義,因為要被派生類重寫,但是語法上可以實現),只要聲明即可
  • 包含純虛函數的類叫做抽象類,抽象類不能實例化出對象
  • 如果派生類繼承后不重寫純虛函數,那么派生類也是抽象類
  • 純虛函數某種程度上強制了派生類重寫虛函數,因為不重寫實例化不出對象

在這里插入圖片描述


4. 多態原理

4.1 虛函數表指針

在這里插入圖片描述


  • 可以看出,對于含有虛函數的類,其內都有一個虛函數表指針vfptr(全稱virtual function ptr),該指針指向虛函數的地址(虛函數表指針可能放在對象前面,也可能放在對象后面,具體看平臺)

4.2 多態的實現

在這里插入圖片描述


在這里插入圖片描述


在這里插入圖片描述


  • 由此可以看出,滿足多態條件后,底層不再是編譯時通過調用對象確定函數的地址,而是運行時到指向的對象的虛表中確定對應的虛函數的地址,這樣就實現了指針或引用指向基類就調用基類的虛函數,指向派生類就調用派生類對應的虛函數
  • 第一張圖,ptr指向的Person對象,調用的是Person的虛函數;第二張圖,ptr指向的Student對
    象,調用的是Student的虛函數

在這里插入圖片描述


  • 多態也可以發生在多個派生類

在這里插入圖片描述


4.3 靜態綁定和動態綁定

  • 對不滿足多態條件的函數,調用時是在編譯階段綁定的,也就是編譯時確定調用該類函數的地址,叫做靜態綁定
  • 滿足多態條件的函數,在運行時,到指向對象的虛函數表中找到調用該類函數的地址,也叫做動態綁定

在這里插入圖片描述


4.4 虛函數表

  • 基類對象的虛函數表中存放基類所有虛函數的地址。同類型的對象共用同一張虛表,不同類型的對象各自有獨立的虛表,所以基類和派生類有各自獨立的虛表
  • 派生類由兩部分構成,繼承下來的基類和自己的成員,一般情況下,繼承下來的基類中有虛函數表指針,自己就不會再生成虛函數表指針。但是要注意的這里繼承下來的基類部分虛函數表指針和基類對象的虛函數表指針不是同一個,就像基類對象的成員和派生類對象中的基類對象成員也獨立的
  • 派生類中重寫的基類的虛函數,派生類的虛函數表中對應的虛函數就會被覆蓋成派生類重寫的虛函數地址
  • 派生類的虛函數表中包含,(1)基類的虛函數地址,(2)派生類重寫的虛函數地址完成覆蓋,派?類自己的虛函數地址三個部分
  • 虛函數表本質是?個存虛函數指針的指針數組,?般情況這個數組最后面放了?個0x00000000標記。(這個C++并沒有進行規定,各個編譯器自行定義的,vs系列編譯器會再后面放個0x00000000標記,g++系列編譯不會放)

在這里插入圖片描述


在這里插入圖片描述


  • 虛函數存在哪的?虛函數和普通函數?樣的,編譯好后是?段指令,都是存在代碼段的,只是虛函數的地址又存到了虛表中
  • 虛函數表存在哪的?這個問題嚴格說并沒有標準答案C++標準并沒有規定,我們寫下面的代碼可以對比驗證?下。vs下是存在代碼段(常量區)

在這里插入圖片描述


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82358.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82358.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82358.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dive into LVGL (1) —— How LVGL works from top to down

0.briefly speaking 由于工作原因,最近開始接觸到一些圖形圖像處理相關的知識,在這個過程中逐漸接觸到了LVGL。作為一個開源的圖形庫,LVGL可以高效地為MCU、MPU等嵌入式設備構建美觀的UI界面。我的手頭也正好有一塊集成了Vivante 2.5D GPU的…

【HarmonyOS 5】鴻蒙中進度條的使用詳解

【HarmonyOS 5】鴻蒙中進度條的使用詳解 一、HarmonyOS中Progress進度條的類型 HarmonyOS的ArkUI框架為開發者提供了多種類型的進度條,每種類型都有其獨特的樣式,以滿足不同的設計需求。以下是幾種常見的進度條類型: 線性進度條(…

OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——gmp

準備工作 請依照這篇文章搭建環境 OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——環境配置_openharmony交叉編譯-CSDN博客 下載 wget https://gmplib.org/download/gmp/gmp-6.3.0.tar.xz 解壓 tar -xf gmp-6.3.0.tar.xzcd gmp-6.3.0/ 環境變量 e…

量化交易策略的運行

? 什么是“策略的運行”? 在量化交易系統中,“策略的運行”并不一定意味著“每個策略對應一個線程”,但在大多數實際實現中,確實會使用線程、任務、協程或進程等形式來實現每個策略的獨立調度與執行。 “運行”意味著策略開始生…

開平機:從原理到實踐的全面技術剖析

一、開平機核心模塊技術解析 1. 校平輥系的力學建模與輥型設計 校平機精度核心在于輥系設計,需通過彈塑性力學模型計算變形量。典型校平輥配置參數: 輥徑比:校平輥直徑(D)與板材厚度(t)需滿足…

2、實驗室測控系統 - /自動化與控制組件/lab-monitoring-system

76個工業組件庫示例匯總 實驗室測控系統開發組件 這是一個專為實驗室設備數據采集與分析設計的可視化測控系統組件。采用工業風格界面設計,提供了豐富的動態數據展示與分析功能,可應用于各類實驗室環境中的設備監控和數據處理。 功能特點 多設備管理…

在 Kotlin 中什么是委托屬性,簡要說說其使用場景和原理

在 Kotlin 中,屬性委托和類委托是兩種通過 by 關鍵字實現的強大特性,它們通過“委托”機制將行為或實現邏輯委托給其他對象,從而實現代碼的復用和解耦。 1 屬性委托 定義: 允許把屬性的 get 和 set 方法的具體實現委托給另一個對…

AI星智協腦:智能驅動的高效協作管理平臺全解讀

前言 想象一下:早上剛開電腦,十幾條未讀消息如機關槍般掃射而來,各路任務像隕石雨一樣砸向你,會議排得比熱播劇還密集,文檔版本堪比宮斗劇劇情反轉,同事圍著你轉圈追KPI,活脫脫一場《職場大逃殺…

Web 架構之數據讀寫分離

文章目錄 一、引言二、數據讀寫分離原理2.1 基本概念2.2 工作流程 三、數據讀寫分離的實現方式3.1 基于中間件實現3.2 應用程序層面實現 四、常見問題及解決方法4.1 數據一致性問題4.2 從數據庫負載均衡問題4.3 主從復制故障問題 五、思維導圖六、總結 一、引言 在 Web應用的開…

【軟件設計師:數據結構】1.數據結構基礎(一)

一 線性表 1.線性表定義 線性表是n個元素的有限序列,通常記為(a1,a2,…,an)。 特點: 存在惟一的表頭和表尾。除了表頭外,表中的每一個元素均只有惟一的直接前驅。除了表尾外,表中的每一個元素均只有惟一的直接后繼。2.線性表的存儲結構 (1)順序存儲 是用一組地址連續…

實踐005-Gitlab CICD全項目整合

文章目錄 環境準備環境準備集成Kubernetes Gitlab CICD項目整合項目整合整合設計 后端Java項目部署后端Java項目靜態檢查后端Java項目鏡像構建創建Java項目部署文件創建完整流水線 前端webui項目部署前端webui項目鏡像構建創建webui項目部署文件創建完整流水線 構建父子類型流水…

鴻蒙開發:dialog庫做了一些優化

前言 本文基于Api13 dialog庫是我去年5月份開發了一個便捷彈窗庫,主打一個使用簡單,一經推出,在dialog領域下載量穩居在前,可以說是非常受歡迎的;但是,之前的版本仍然有著可優化的空間,比如彈窗…

Windows 10 無法啟動或黑屏的修復指南(適用于更新失敗或磁盤故障)

Windows 10 無法啟動或黑屏的修復指南(適用于更新失敗或磁盤故障) 當 Windows 10 突然無法啟動(黑屏、無限重啟、更新失敗后斷電等情況),很可能是由于啟動引導程序損壞或系統映像異常(如系統磁盤出現壞道&…

MCP開發入門

MCP開發入門 官方文檔: https://modelcontextprotocol.io/introduction 入門教程: https://github.com/liaokongVFX/MCP-Chinese-Getting-Started-Guide 本文源代碼:https://github.com/youngqqcn/mcp-server-demo 什么是MCP? 模型上下文協議&#xff…

PX4開始之旅(二)通過自定義 MAVLink 消息與 QGroundControl (QGC) 通信

核心知識點:通過自定義 MAVLink 消息與 QGroundControl (QGC) 通信 1. 通俗易懂的解釋 想象一下,MAVLink 就像是無人機(飛控)和地面站(QGroundControl)之間約定好的一種“語言”。這種語言有很多標準的“…

AI視頻智能分析網關打造社區/工廠/校園/倉庫智慧消防實現精準化安全管控

一、背景 隨著社區、商業場所對消防安全要求日益提升,傳統消防系統已難以滿足智能化、精細化管理需求。智能分析網關融合物聯網與人工智能技術,具備強大的數據處理與分析能力,可全面升級消防系統。將其融入消防系統各層級,搭建智…

深度學習基礎--目標檢測常見算法簡介(R-CNN、Fast R-CNN、Faster R-CNN、Mask R-CNN、SSD、YOLO)

博主簡介:努力學習的22級本科生一枚 🌟?;探索AI算法,C,go語言的世界;在迷茫中尋找光芒?🌸? 博客主頁:羊小豬~~-CSDN博客 內容簡介:常見目標檢測算法簡介?&#x1f…

傳輸層協議UDP和TCP

傳輸層協議UDP和TCP 1、UDP2、TCP2.1、TCP協議段格式2.2、確認應答(ACK)機制2.3、超時重傳機制2.4、連接管理機制2.5、理解CLOSE_WAIT狀態2.6、理解TIME_WAIT狀態2.7、流量控制2.8、滑動窗口2.9、擁塞控制2.10、延遲應答2.11、捎帶應答2.12、面向字節流2.13、粘包問題2.14、TCP…

PMIC電源管理模塊的PCB設計

目錄 PMU模塊簡介 PMU的PCB設計 PMU模塊簡介 PMIC(電源管理集成電路)是現代電子設備的核心模塊,負責高效協調多路電源的轉換、分配與監控。它通過集成DC-DC降壓/升壓、LDO線性穩壓、電池充電管理、功耗狀態切換等功能,替代傳統分…

Ubuntu 配置網絡接口端點(靜態 IP 地址)詳細教程

在 Ubuntu 系統中,配置網絡接口端點通常指的是為您的有線或無線網卡設置一個固定的 IP 地址、子網掩碼、網關以及 DNS 服務器。這對于服務器或者需要穩定網絡標識的設備來說非常重要。 使用 Netplan (Ubuntu 17.10 及更高版本的默認方式)使用 ifupdown (通過 /etc/…