C++入門小館 :多態

嘿,各位技術潮人!好久不見甚是想念。生活就像一場奇妙冒險,而編程就是那把超酷的萬能鑰匙。此刻,陽光灑在鍵盤上,靈感在指尖跳躍,讓我們拋開一切束縛,給平淡日子加點料,注入滿滿的passion。準備好和我一起沖進代碼的奇幻宇宙了嗎?Let's go!

我的博客:yuanManGan

我的專欄:C++入門小館?C言雅韻集?數據結構漫游記? 閑言碎語小記坊?題山采玉?領略算法真諦

目錄

多態的概念:

構成多態的條件:

虛函數:

虛函數的重寫/覆蓋:

? 協變(了解)

析構函數的重寫:

override 和 final關鍵字

重載/重寫/隱藏的對?

?純虛函數和抽象類

多態的原理:

虛函數表指針:

虛函數表:


面向對象三大特性:封裝,繼承,多態。今天來講講最后一個多態。

多態的概念:

多態是針對函數來說的,當函數名相同時,我們傳入不同的參數會出現不同的效果,這就是多態。多態又分為靜態多態,和動態多態,靜態指的一般是函數重載和模板(又叫作編譯時多態),而我們今天的重點是動態多態(也叫作運行時多態)

動態多態就是,當你傳入不同的對象時(函數),會出現不一樣的結果,比如我們買火車票,如果你是學生會打折,成人就是全票,而軍人就是優先買票。再?如,同樣是動物叫的?個?為(函數),傳貓對象過去,就是”(>^ω^<) 喵“,傳狗對象過去,就是"汪汪"。

構成多態的條件:

? 必須是基類的指針或者引?調?虛函數
? 被調?的函數必須是虛函數,并且完成了虛函數重寫/覆蓋。
多態是?個繼承關系的下的類對象,去調?同?函數,產?了不同的?為。?如Student繼承了
Person。Person對象買票全價,Student對象優惠買票。
說明:要實現多態效果,第?必須是 基類的指針或引? ,因為只有基類的指針或引?才能既指向基類 對象?指向派?類對象;第?派?類必須對基類的虛函數 完成重寫/覆蓋 ,重寫或者覆蓋了,基類和派 ?類之間才能有不同的函數,多態的不同形態效果才能達到。

這里補充一下:

虛函數:

類成員函數前?加virtual修飾,那么這個成員函數被稱為虛函數。注意?成員函數不能加virtual修
飾。

虛函數的重寫/覆蓋:

派生類里面的一個虛函數和父類的虛函數有三同:
1.返回值相同
2.參數相同
3.函數名相同
注意:我們如果父類加了virtual,子類可以不加virtual依然可以構成虛函數,但實踐中不建議這樣做,選擇題經常有這個坑。
class Person {
public:virtual void BuyTicket() { cout << "買票-全價" << endl; }
};
class Student : public Person {
public:virtual void BuyTicket() { cout << "買票-打折" << endl; }
};
void Func(Person* ptr)
{// 這?可以看到雖然都是Person指針Ptr在調?BuyTicket// 但是跟ptr沒關系,?是由ptr指向的對象決定的。ptr->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);Func(&st);return 0;
}

?

class Animal
{
public:virtual void talk() const{}
};
class Dog : public Animal
{
public:virtual void talk() const{std::cout << "汪汪" << std::endl;}
};
class Cat : public Animal
{
public:virtual void talk() const{std::cout << "(>^ω^<)喵" << std::endl;}
};
void letsHear(const Animal& animal)
{animal.talk();
}
int main()
{Cat cat;Dog dog;letsHear(cat);letsHear(dog);return 0;
}

這里的對虛函數的重寫,其實是重寫的實現。

? 協變(了解)

派?類重寫基類虛函數時,與基類虛函數返回值類型可以不同,可以都是 基類對象的指針或者引
?,而這種情況我們稱之為協變。
class A {};
class B : public A {};
class Person {
public:virtual A* BuyTicket(){cout << "買票-全價" << endl;return nullptr;}
};
class Student : public Person {
public:virtual B* BuyTicket(){cout << "買票-打折" << endl;return nullptr;}
};
void Func(Person* ptr)
{ptr->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);Func(&st);return 0;
}

這樣寫沒有很大的意義,我們很少這么實現。

析構函數的重寫:

我們定義了兩個A類型的指針分別指向A和B對象,但我們析構時為什么沒有析構B對象呢?因為我們的p2是指向A類型的,然后我們析構是調用A類型的析構。那我們該怎樣調用B的析構函數呢?這里就要用到多態了,但我們的析構的函數名不是不相同嗎,怎么實現重寫呢?其實編譯器會將你寫的析構函數的函數名看成一樣的Destruct,這就導致我們繼承遇到的析構函數為什么會隱藏,這里將A的析構寫成隱藏就可以解決了。

override 和 final關鍵字

final關鍵字我們之前用來定義一個不能被繼承的類,這里可以用它來定義一個不能被重寫的虛函數。

override 用來檢查一個虛函數是否被重寫,沒有就會報錯。

重載/重寫/隱藏的對?

?純虛函數和抽象類

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

多態的原理:

虛函數表指針:

該程序的運行結果(32位的環境下)是什么呢?

有人說是8不就是兩個成員嗎,內存對齊一下就是8,其實我們有虛函數的類里面還有一個虛函數表指針,指向虛函數表。

?所以答案是12。

我們實現虛函數的重寫其實就是將虛函數表指針進行重寫。使他指向不同的對象,我們無論傳入的派生類是怎么樣的,傳入Func函數都會進行截斷,是它只出現父類,然后通過虛函數表指針調用函數,這就形成了多態。

虛函數表:

基類對象的虛函數表中存放基類所有虛函數的地址。同類型的對象共?同?張虛表,不同類型的對
象各?有獨?的虛表,所以基類和派?類有各?獨?的虛表。
所以我們不要什么函數都弄成虛函數。
派?類由兩部分構成,繼承下來的基類和??的成員,?般情況下,繼承下來的基類中有虛函數表
指針,??就不會再?成虛函數表指針。但是要注意的這?繼承下來的基類部分虛函數表指針和基
類對象的虛函數表指針不是同?個,就像基類對象的成員和派?類對象中的基類對象成員也獨?
的。
派?類中重寫的基類的虛函數,派?類的虛函數表中對應的虛函數就會被覆蓋成派?類重寫的虛函
數地址。
虛函數表本質是?個存虛函數指針的指針數組,?般情況這個數組最后?放了?個0x00000000標
記。(這個C++并沒有進?規定,各個編譯器??定義的,vs系列編譯器會再后?放個0x00000000
標記,g++系列編譯不會放)
虛函數存在哪的?虛函數和普通函數?樣的,編譯好后是?段指令,都是存在代碼段的,只是虛函
數的地址?存到了虛表中。
虛函數表存在哪的?這個問題嚴格說并沒有標準答案C++標準并沒有規定,我們寫下?的代碼可以
對?驗證?下。vs下是存在代碼段(常量區)

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

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

相關文章

【NextPilot日志移植】整體功能概要

整體日志系統的實現功能 該日志系統主要實現了飛行日志的記錄功能&#xff0c;支持多種日志記錄模式&#xff0c;可將日志存儲到文件或通過 MAVLink 協議傳輸&#xff0c;同時具備日志加密、空間管理、事件記錄等功能。具體如下&#xff1a; 日志記錄模式&#xff1a;支持按武…

數字化轉型:概念性名詞淺談(第二十五講)

大家好&#xff0c;今天接著介紹數字化轉型的概念性名詞系列。 &#xff08;1&#xff09;SOP(標準作業程序) 標準作業程序&#xff08;Standard Operating Procedure, SOPs&#xff09;是在有限時間與資源內&#xff0c;為了執行復雜的日常事務所設計的內部程序。從管理學的…

交叉編譯 opencv-4.10

編譯說明 opencv 下包含很多模塊&#xff0c;各個模塊的作用可以參考Opencv—模塊概覽. 嵌入式考慮有限存儲等因素會對模塊進行裁剪&#xff0c;我這里主要保留圖像拼接&#xff08;stitching&#xff09;圖片編解碼&#xff08;imgcodecs&#xff09;與特征點匹配&#xff08…

Python cv2對象檢測與跟蹤:從基礎到進階實戰

在計算機視覺領域&#xff0c;對象檢測&#xff08;定位目標位置&#xff09;與對象跟蹤&#xff08;持續追蹤目標運動&#xff09;是視頻分析、自動駕駛、智能監控等應用的核心技術。本文將結合OpenCV的cv2庫&#xff0c;系統講解其原理與Python實現方法。 一、對象檢測 vs 對…

亞馬遜推出新型倉儲機器人 Vulcan:具備“觸覺”但不會取代人類工人

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

緩存套餐-03.功能測試

一.功能測試 點擊小程序&#xff0c;就會觸發根據分類id查詢套餐方法&#xff0c;根據分類id查詢套餐。 第一次查詢&#xff0c;redis中沒有數據&#xff0c;就會發sql進行sql數據庫查詢。 redis當中就有了對應的緩存。 再次點擊&#xff0c;發現sql根本沒有執行&#xff0c;…

WebFlux與HttpStreamable關系解析

1-Streamable 1-WebFlux與HttpStreamable關系解析2-MCP協議Streamable HTTP 2-參考網址 MCP協議Streamable HTTPMCP協議重大升級&#xff0c;Spring AI Alibaba聯合Higress發布業界首個Streamable HTTP實現方案 3-WebFlux與HttpStreamable關系解析 WebFlux 和 HttpStreamabl…

順豐科技:從 Presto 到 Doris 湖倉構架升級,提速 3 倍,降本 48%

導讀&#xff1a;順豐科技引入 Doris 替換 Presto&#xff0c;在內部可視化數據自助分析工具豐景臺場景廣泛應用。目前&#xff0c;順豐臨時查詢業務、豐景臺報表業務的 Presto 場景已經 100% 切換到 Doris 集群中&#xff0c;日均查詢量 100W。并實現 P95 性能提升近 3 倍&…

如何在Jmeter中調用C程序?

在JMeter中調用C語言程序可以通過以下幾種方式實現&#xff1a; 方法一&#xff1a;使用OS Process Sampler JMeter的“OS Process Sampler”可以用來調用外部程序&#xff0c;包括C語言編寫的可執行文件。 步驟&#xff1a; 準備C語言程序&#xff1a; 編寫C語言代碼并編譯…

python 中的單例

在 Python 里&#xff0c;單例模式指的是一個類僅有一個實例&#xff0c;并且提供一個全局訪問點來獲取該實例。下面為你介紹幾種實現單例模式的常見方法。 1. 使用模塊 在 Python 里&#xff0c;模塊天然就是單例模式。當模塊被導入時&#xff0c;Python 會對其進行一次加載…

Linux58 ssh服務配置 jumpserver 測試雙網卡 為何不能ping通ip地址

判斷為NAT模式網卡 能ping 通外網 ens34為僅主機模式網卡 [rootlocalhost network-scripts]# ip route show default default via 10.1.1.254 dev ens33 proto static metric 100 10.0.0.0/8 dev ens33 proto kernel scope link src 10.1.1.37 metric 100 11.0.0.0/8 dev…

web 自動化之 selenium+webdriver 環境搭建及原理講解

文章目錄 一、web 自動化測試學習說明二、什么 web 自動化測試三、selenium 簡介四、web自動化測試環境搭建五、web 自動化測試第一個腳本六、selenium 原理及源碼講解 一、web 自動化測試學習說明 進階 web 自動化測試學習&#xff1a;掌握 python 編程基礎 二、什么 web 自…

Linux 網絡命名空間:從內核資源管理到容器網絡隔離

1. 網絡命名空間是什么? 網絡命名空間(Network Namespace) 是 Linux 內核提供的一種網絡資源隔離機制,用于為進程或容器創建完全獨立的網絡環境。它并非物理或虛擬的網絡接口(如網卡、veth pair 等),而是一個虛擬容器,包含以下資源的獨立實例: 網絡接口(物理或虛擬)…

SQL知識點總結

總結的知識點主要來源于前段時間在牛客刷SQL題目中遇到的錯誤 目錄 1.WHERE字句不能與高級函數連用 2.去重——distinct 3.不等于某個值 4.查多個范圍內的值 5. 升/降序排序 6.占位符 7.統計某類別總數計算平均值 8.合并查詢——UNION &#xff08;ALL&#xff09; 9…

【軟考-高級】【信息系統項目管理師】【論文基礎】采購管理過程輸入輸出及工具技術的使用方法

采購管理概念 項目采購管理包括從項目團隊外部采購或獲取所需產品、服務或成果的各個過程。項目采購管理包括編制和管理協議所需的管理和控制過程&#xff0c;例如合同、訂購單、協議備忘錄&#xff08;MOA&#xff09;和服務水平協議&#xff08;SLA&#xff09;。 采購管理…

C++ 手寫一個內存池

內存池是一種內存管理技術&#xff0c;它預先分配一大塊內存&#xff0c;之后將其按需分割成多個小塊供程序使用。下面將詳細闡述它的好處以及適用場景。 內存池的好處 減少內存碎片&#xff1a;在動態內存分配時&#xff0c;頻繁地分配和釋放不同大小的內存塊&#xff0c;會…

LeetCode 3341.到達最后一個房間的最少時間 I:Dijkstra算法(類似深搜)-簡短清晰的話描述

【LetMeFly】3341.到達最后一個房間的最少時間 I&#xff1a;Dijkstra算法&#xff08;類似深搜&#xff09;-簡短清晰的話描述 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/find-minimum-time-to-reach-last-room-i/ 有一個地窖&#xff0c;地窖中有 n x m 個房間…

學習Linux的第四天

今天我們來學習Linux的網絡配置&#xff0c;以及鏈表的知識開個小頭 三種網絡配置模式 橋接模式&#xff08;用的最多&#xff09; 2.Nat模式 3. 僅主機模式&#xff08;Nat模式的功能外&#xff0c;只能在局域網通信&#xff0c;不能訪問外網&#xff09; 橋接模式&#xf…

【 window.addEventListener(‘message‘, handleMessage)無效的問題】

在react native加載中可能出現 window.addEventListener(‘message’, handleMessage)無效&#xff0c;無法監聽到在react-native-webview中通過postMessage發送的消息&#xff0c;可以通過下面的方法來處理 window.addEventListener(message, handleMessage);document.addEven…

css識別\n換行

在CSS中&#xff0c;\n 通常不會被識別為換行符。如果你希望在CSS中實現換行效果&#xff0c;可以使用以下幾種方法&#xff1a; 使用 white-space 屬性&#xff1a; 設置 white-space: pre 或 white-space: pre-wrap&#xff0c;這樣文本中的換行符 \n 會被保留并顯示為換行。…