【C++】一文簡練總結【多態】及其底層原理&具體應用(21)

前言

大家好吖,歡迎來到 YY 滴C++系列 ,熱烈歡迎! 本章主要內容面向接觸過C++的老鐵
主要內容含:
在這里插入圖片描述

歡迎訂閱 YY滴C++專欄!更多干貨持續更新!以下是傳送門!

目錄

  • 一.多態的概念
  • 二.多態的實現
    • 1)虛函數&虛函數表
    • 2)虛函數的重寫(覆蓋)
    • 3)多態的構成條件
    • 4)虛函數重寫的兩種特殊情況:
        • 【1】協變:(基類與派生類虛函數返回值類型不同)
        • 【2】析構函數的重寫:(基類與派生類析構函數的名字不同)
  • 三.【override】【final】關鍵字——幫助用戶檢測是否重寫(C++11)
      • 【1】 final:表示虛函數不能被重寫,被重寫即報錯
      • 【2】override:檢查虛函數是否重寫了別的虛函數,重寫了即報錯
  • 四. 多態的具體應用:抽象類(接口類)(純虛函數類)
      • 1)利用 [ 只有重寫純虛函數 派生類才能實例化出對象 ] 性質
      • 2)實現繼承與接口繼承

一.多態的概念

  • 多態是在不同繼承關系的類對象,去調用 同一 函數,產生了 不同 的行為。比如Student繼承了Person。Person對象買票全價,Student對象買票半價。
  • 例:iphone和安卓手機用戶打車同程不同價

二.多態的實現

1)虛函數&虛函數表

  • 虛函數:即被 virtual 修飾的類成員函數稱為虛函數。
class Person {
public:virtual void BuyTicket() { cout << "買票-全價" << endl;}
};
  • 虛函數表本質是一個存虛函數指針 指針數組,一般情況這個數組最后面放了一個nullptr。
  • 虛函數表:虛函數表存的是虛函數指針,不是虛函數,虛函數和普通函數一樣的,都是存在代碼段的,只是他的指針又存到了虛函數表中。
  • 一個含有虛函數的類中都至少都有一個虛函數表指針,因為虛函數的地址要被放到虛函數表中,虛函數表也簡稱虛表

2)虛函數的重寫(覆蓋)

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

3)多態的構成條件

  1. 必須通過 基類的指針 引用 調用虛函數
  2. 被調用的函數 必須是虛函數,且 派生類必須對基類的虛函數進行重寫
                                           //多態條件2:被調用的函數 必須是虛函數
class Person {
public:virtual void BuyTicket() { cout << "買票-全價" << endl; }
};
class Student : public Person {
public:                                   //多態條件2:派生類必須對基類的虛函數進行重寫virtual void BuyTicket() { cout << "買票-半價" << endl; }
/*注意:在重寫基類虛函數時,派生類的虛函數在不加virtual關鍵字時,雖然也可以構成重寫(因
為繼承后基類的虛函數被繼承下來了在派生類依舊保持虛函數屬性),但是該種寫法不是很規范,不建議
這樣使用*/
/*void BuyTicket() { cout << "買票-半價" << endl; }*/
};void Func(Person& p)       //多態條件1:必須通過基類的指針來“引用”調用虛函數
{ 
p.BuyTicket(); 
}int main()
{
Person ps;
Student st;
Func(ps);
Func(st);return 0;
}

4)虛函數重寫的兩種特殊情況:

【1】協變:(基類與派生類虛函數返回值類型不同)
  • 派生類重寫基類虛函數時 ,與基類虛函數 返回值類型不同 。即如下代碼所示:【基類虛函數返回基類對象的指針或者引用,派生類虛函數返回派生類對象的指針或者引用時】,稱為協變
class A{};
class B : public A {};
class Person {
public:virtual A* f() {return new A;}
};
class Student : public Person {
public:virtual B* f() {return new B;}
};
【2】析構函數的重寫:(基類與派生類析構函數的名字不同)
  • 如果 基類的析構函數為虛函數 ,此時派生類析構函數只要定義, 無論是否加virtual關鍵字
    都與基類的析構函數構成重寫,雖然基類與派生類析構函數名字不同。 雖然函數名不相同【~Person() 】 【~Student() 】,看起來違背了重寫的規則,其實不然,這里可以理解為編譯器對析構函數的名稱做了特殊處理,編譯后析構函數的名稱統一處理成 destructor
class Person {
public:                  //基類的析構函數為虛函數virtual ~Person() {cout << "~Person()" << endl;}
};class Student : public Person {
public://~Student() { cout << "~Student()" << endl; 不加virtual也行virtual ~Student() { cout << "~Student()" << endl; }
};
// 只有派生類Student的析構函數重寫了Person的析構函數,下面的delete對象調用析構函數,
//才能構成多態,才能保證p1和p2指向的對象正確的調用析構函數。
int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0;
}

三.【override】【final】關鍵字——幫助用戶檢測是否重寫(C++11)

  • 從上面可以看出,C++對函數重寫的要求比較嚴格,但是有些情況下由于疏忽,可能會導致函數
    名字母次序寫反而無法構成重載,而這種錯誤在編譯期間是不會報出的,只有在程序運行時沒有
    得到預期結果才來debug會得不償失,因此:C++11從兩個角度提供了 override final 兩個關鍵字,可以幫
    助用戶檢測是否重寫。
  • final:表示虛函數不能被重寫,被重寫即報錯
  • override:檢查虛函數是否重寫了別的虛函數,重寫了即報錯

【1】 final:表示虛函數不能被重寫,被重寫即報錯

class Car
{
public:virtual void Drive() final {}
};
class Benz :public Car
{
public:virtual void Drive() {cout << "Benz-舒適" << endl;}
};

【2】override:檢查虛函數是否重寫了別的虛函數,重寫了即報錯

class Car{
public:virtual void Drive(){}
};
class Benz :public Car {
public:virtual void Drive() override {cout << "Benz-舒適" << endl;}
};

四. 多態的具體應用:抽象類(接口類)(純虛函數類)

1)利用 [ 只有重寫純虛函數 派生類才能實例化出對象 ] 性質

  • 在虛函數的后面寫上 =0 ,則這個函數為 純虛函數 包含純虛函數的類 叫做 抽象類(也叫接口類) [ 抽象類不能實例化出對象 ]&[ 派生類繼承后也不能實例化出對象 ] 只有 [ 重寫純虛函數 ] ,派生類才能實例化出對象。純虛函數規范了派生類必須重寫,另外純虛函數更體現出了接口繼承。
class Car
{
public:
virtual void Drive() = 0;         //在虛函數的后面寫上 =0,這個函數為 純虛函數
};class Benz :public Car
{
public:virtual void Drive(){cout << "Benz-舒適" << endl;  //只有 [ 重寫純虛函數 ] ,派生類才能實例化出對象}
};class BMW :public Car
{
public:virtual void Drive(){cout << "BMW-操控" << endl;}
};void Test()
{
Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();
}

2)實現繼承與接口繼承

  • 普通函數的繼承是一種 實現繼承 ,派生類繼承了基類函數,可以使用函數,繼承的是函數的實現。
  • 虛函數的繼承是一種 接口繼承 ,派生類繼承的是基類虛函數的接口, 目的是為了重寫,達成多態 ,繼承的是接口。所以如果不實現多態,不要把函數定義成虛函數。

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

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

相關文章

【C++】:拷貝構造函數與賦值運算符重載的實例應用之日期類的實現

C實現日期類 ├─屬性&#xff1a; │ ├─年份 │ ├─月份 │ └─日期 ├─方法&#xff1a; │ ├─構造函數 │ ├─拷貝構造函數 │ ├─析構函數 │ ├─設置年份 │ ├─設置月份 │ ├─設置日期 │ ├─獲取年份 │ ├─獲取月份 │ ├─獲取日期 │ ├…

websocket和mqtt

WebSocket是一種通信協議&#xff0c;它允許在瀏覽器和服務器之間建立持久連接&#xff0c;并允許雙向傳遞數據。MQTT則是一種輕量級的發布/訂閱消息傳輸協議&#xff0c;常用于物聯網(IoT)設備之間的通信。 &#xff08;1&#xff09;js能直接實現mqtt嗎&#xff0c;還是需…

已解決java.lang.IllegalStateException: Duplicate key

已解決java.lang.IllegalStateException: Duplicate key 文章目錄 報錯問題解決思路解決方法交流 報錯問題 java.lang.IllegalStateException: Duplicate key 解決思路 java.lang.IllegalStateException: Duplicate key 是由于在使用 Map 或 Set 時&#xff0c;試圖將一個已經…

十、sdl顯示yuv圖片

前言 SDL中內置加載BMP的API&#xff0c;使用起來會更加簡單&#xff0c;便于初學者學習使用SDL 如果需要加載JPG、PNG等其他格式的圖片&#xff0c;可以使用第三方庫&#xff1a;SDL_image 測試環境&#xff1a; ffmpeg的4.3.2自行編譯版本windows環境qt5.12sdl2.0.22&…

redis的性能管理和雪崩

redis的性能管理 redis的數據是緩存在內存當中的 系統巡檢&#xff1a; 硬件巡檢、數據庫、nginx、redis、docker、k8s 運維人員必須要關注的redis指標 在日常巡檢中需要經常查看這些指標使用情況 info memory #查看redis使用內存的指標 used_memory:11285512 #數據占用的…

最簡單的簡歷練習

代碼&#xff1a; <!DOCTYPE html> <html> <head> <title>我的簡歷</title> <style> body { background-image: url(https://picsum.photos/id/1018/1000/1000); background-size: cover; …

已解決java.lang.RuntimeException: java.io.IOException: invalid constant type: 18異常的正確解決方法,親測有效!!!

已解決java.lang.RuntimeException: java.io.IOException: invalid constant type: 18異常的正確解決方法&#xff0c;親測有效&#xff01;&#xff01;&#xff01; 文章目錄 報錯問題解決方法交流 報錯問題 java.lang.RuntimeException: java.io.IOException: invalid cons…

完美解決ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python36\pyt

完美解決ERROR: Command errored out with exit status 1: command: f:\program files\python\python36\pyt 下滑查看解決方法 文章目錄 報錯問題解決思路解決方法交流 報錯問題 ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python3…

【華為OD】C卷真題 100%通過:攀登者1 C/C++源碼實現

【華為OD】C卷真題 100%通過&#xff1a;攀登者1 C/C源碼實現 目錄 題目描述&#xff1a; 示例1 代碼實現&#xff1a; 題目描述&#xff1a; 攀登者喜歡尋找各種地圖&#xff0c;并且嘗試攀登到最高的山峰。 地圖表示為一維數組&#xff0c;數組的索引代表水平位置&…

C++二分查找算法:有序矩陣中的第 k 個最小數組和

本文涉及的基礎知識點 二分查找算法合集 本題的簡化 C二分查找算法&#xff1a;查找和最小的 K 對數字 十分接近m恒等于2 題目 給你一個 m * n 的矩陣 mat&#xff0c;以及一個整數 k &#xff0c;矩陣中的每一行都以非遞減的順序排列。 你可以從每一行中選出 1 個元素形成…

哈希unordered_set,unordered_map的練習

349. 兩個數組的交集 給定兩個數組 nums1 和 nums2 &#xff0c;返回 它們的交集 。輸出結果中的每個元素一定是 唯一 的。我們可以 不考慮輸出結果的順序 。 示例 1&#xff1a; 輸入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 輸出&#xff1a;[2]示例 2&#xff1a; 輸…

JSP過濾器和監聽器

什么是過濾器 Servlet過濾器與Servlet十分相似&#xff0c;但它具有攔截客戶端&#xff08;瀏覽器&#xff09;請求的功能&#xff0c;Servlet過濾器可以改變請求中的內容&#xff0c;來滿足實際開發中的需要。 對于程序開發人員而言&#xff0c;過濾器實質就是在Web應用服務器…

使用Wireshark提取流量中圖片方法

0.前言 記得一次CTF當中有一題是給了一個pcapng格式的流量包&#xff0c;flag好像在某個響應中的圖片里。比較簡單&#xff0c;后來也遇到過類似的情況&#xff0c;所以總結和記錄一下使用Wireshark提取圖片的方法。 提取的前提是HTTP協議&#xff0c;至于HTTPS的協議需要導入服…

【算法】摩爾投票算法

目錄 1.概述2.算法思想3.代碼實現3.1.t ?n / 2?3.2.t ?n / 3?3.3.t ?n / (m 1)? 4.應用 參考&#xff1a;LeetCode_多數元素 II 題解 1.概述 &#xff08;1&#xff09;摩爾投票法 (Boyer–Moore Majority Vote Algorithm) 是一種用來尋找一組元素中多數元素的常量級…

flutter,uni-app開發調試ios

一、申請ios開發者賬號 二、ios開發者配置 ios 開發者需要配置的地方 https://developer.apple.com/account/resources/certificates/list Certificates&#xff08;證書&#xff09;: 作用&#xff1a; 證書用于對應用程序和開發者進行身份驗證&#xff0c;確保安全性和可…

如何為您的企業選擇合適的多因素認證?

在傳統的網絡安全架構中&#xff0c;重點在于防止非法入侵&#xff0c;例如防火墻、VPN 、堡壘機等安全設備的重心都在于防止用戶違規訪問企業資源&#xff0c;一旦合法用戶的賬號密碼被入侵者拿到&#xff0c;就可以冒充合法用戶訪問企業資源&#xff0c;所有的安全設備形同虛…

springcloud超市管理系統源碼

技術說明&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;idea&#xff0c;vscode springcloud springboot mybatis vue elementui mysql 功能介紹&#xff1a; 后臺管理&#xff1a; 統計分析&#xff1a;查看用戶&#xff0c;商品&#xff0c;銷售數量&#xff1b;…

Mock 數據

1. Mock 數據的方式 2. json-server 實現 Mock 數據 項目中安裝json-server npm i -D json-server準備一個json文件添加啟動命令 //package.json"scripts": {"start": "craco start","build": "craco build","test&q…

簡單聊聊加密和加簽的關系與區別

大家好&#xff0c;我是G探險者。 平時我們在項目上一定都聽過加密和加簽&#xff0c;加密可能都好理解&#xff0c;知道它是保障的數據的機密性&#xff0c;那加簽是為了保障啥勒&#xff1f;它和加密有啥區別&#xff1f; 帶著這個疑問&#xff0c;我們就來聊聊二者的區別。…

SHEIN出口車鑰匙扣REACH認證指南解析

鑰匙扣的材料一般為金屬、皮革、塑料、橡膠、木頭等。此物精致小巧、造型千變萬化是人們隨身攜帶的日常用品。鑰匙扣是掛在鑰匙圈上的一種裝飾物品。鑰匙扣出口需要辦理REACH認證。 一、什么是REACH認證&#xff1f; REACH認證是歐盟28個成員國對進入其市場的所有化學品,&…