C++中多態的概念和意義

来源:https://www.cnblogs.com/dishengAndziyu/archive/2019/05/23/10915253.html
-Advertisement-
Play Games

1,函數重寫回顧: 1,父類中被重寫的函數依然會繼承給子類; 2,子類中重寫的函數將覆蓋父類中的函數; 1,重寫父類當中提供的函數是因為父類當中提供的這個函數版本不能滿足我們的需求,因此我們要重寫; 2,期望只要是子類對象,則調用子類當中的版本,而不是父類當中定義的函數版本; 3,通過作用域分辨符( ...


1,函數重寫回顧:

    1,父類中被重寫的函數依然會繼承給子類;

    2,子類中重寫的函數將覆蓋父類中的函數;

       1,重寫父類當中提供的函數是因為父類當中提供的這個函數版本不能滿足我們的需求,因此我們要重寫;

       2,期望只要是子類對象,則調用子類當中的版本,而不是父類當中定義的函數版本;

    3,通過作用域分辨符(::)可以訪問到父類中的函數;

       1,代碼示例:

Child c;
Parent* p = &c;
           
c.Parent::print();  // 從父類中繼承;I'm Parent.
c.print();  // 在子類中重寫;I'm Child.
           
p->print();  // 父類中定義;I'm Parent.不是我們期望的版本,因為 p 指向了子類對象,期望調用子類版本

 

2,面相對象中期望的行為:

    1,根據實際的對象類型判斷如何調用重寫函數;

       1,而不是根據指針類型(編譯器預設的安全行為);

    2,父類指針(引用)指向:

       1,父類對象,則調用父類中定義的函數;

       2,子類對象,則調用子類中定義的重寫函數;

      

3,面向對象中的多態的概念:

    1,根據實際的對象類型決定函數調用的具體目標;

       1,相同的行為方式可能導致不同的行為結果,即產生了多種形態行為,即多態;

    2,同樣的調用語句在實際運行時有多種不同的表現形態;

       1,同一行語句展現了多種不同的表現形態,多態本質;      

   

4,C++ 語言直接支持多態的概念:

    1,通過使用 virtual 關鍵字對多態進行支持;

       1,什麼時候用 virtual ?

       2,定義類的時候,覺得某一個函數在後續被繼承的過程當中,有可能被重寫,就是用 virtual 關鍵字修飾這個函數;

    2,被 virtual 聲明的函數被重寫後具有多態特性;

       1,函數名和參數都必須一樣,若函數名相同但參數不同,這是同名覆蓋;

    3,被 virtual 聲明的函數叫做虛函數(因為 virtual 的意思就是虛擬的);

       1,虛函數被繼承後依然是虛函數,不用再被 virtual 修飾;

      

5,多態的初體驗編程實驗:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Parent
 7 {
 8 public:
 9     virtual void print()  // 這個函數可能被繼承的子類重寫,所以加上virtual 關鍵字來修飾它,稱為虛函數,實現多態;
10     {
11         cout << "I'm Parent." << endl;
12     }
13 };
14 
15 class Child : public Parent
16 {
17 public:
18     void print()  // 雖然沒有寫 virtual 關鍵字,但是由於繼承的關係,它就是虛函數;一般工程中沒必要在子類中寫 virtual;
19     {
20         cout << "I'm Child." << endl;
21     }
22 };
23 
24 void how_to_print(Parent* p)
25 {
26     p->print();     // 希望展現多態行為;
27 }
28 
29 int main()
30 {
31     Parent p;
32     Child c;
33     
34     how_to_print(&p);    // 期望列印: I'm Parent.  實際列印:I'm Parent.
35     how_to_print(&c);    // 期望列印: I'm Child.  實際列印:I'm Child.
36     
37     return 0;
38 }

   

6,多態意義:

    1,在程式運行過程中展現出動態的特性;

       1,編譯時無法決定究竟調用哪一個版本的實現;

    2,函數重寫必須多態實現,否則沒有意義;

       1, C++ 後續語言(Java、C#)中,只要是重寫,一定是虛函數,不需要顯示聲明 virtual 關鍵字;

    3,多態是面向對象組件化程式設計的基礎特性;

       1,後續學習中多態特性會被變著花樣玩兒,特別是設計模式中絕大多數模式都和多態相關;

   

7,理論中的概念:

    1,靜態聯編:

       1,在程式的編譯期間就能確定具體的函數調用;

           1,如函數重載;

   2,動態聯編(多態):

       1,在程式實際運行後才能確定具體的函數調用;

           1,如函數重寫;

          

8,動態聯編與靜態聯編實例分析:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Parent
 7 {
 8 public:
 9     virtual void func()
10     {
11         cout << "void func()" << endl;
12     }
13     
14     virtual void func(int i)
15     {
16         cout << "void func(int i) : " << i << endl;
17     }
18     
19     virtual void func(int i, int j)
20     {
21         cout << "void func(int i, int j) : " << "(" << i << ", " << j << ")" << endl;
22     }
23 };
24 
25 class Child : public Parent
26 {
27 public:
28     void func(int i, int j)
29     {
30         cout << "void func(int i, int j) : " << i + j << endl;
31     }
32     
33     void func(int i, int j, int k)  // 子類同名覆蓋父類當中的函數,重載同一作用域當中的函數;
34     {
35         cout << "void func(int i, int j, int k) : " << i + j + k << endl;
36     }
37 };
38 
39 void run(Parent* p)
40 {
41     p->func(1, 2);     // 展現多態的特性,動態聯編
42 }
43 
44 int main()
45 {
46     Parent p;
47     
48     p.func();         // 靜態聯編
49     p.func(1);        // 靜態聯編
50     p.func(1, 2);     // 靜態聯編
51     
52     cout << endl;
53     
54     Child c;
55     
56     c.func(1, 2);     // 靜態聯編
57     
58     cout << endl;
59     
60     run(&p);
61     run(&c);
62     
63     return 0;
64 }

   

9,多態編程實驗:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Boss
 7 {
 8 public:
 9     int fight()
10     {
11         int ret = 10;
12         
13         cout << "Boss::fight() : " << ret << endl;
14         
15         return ret;
16     }
17 };
18 
19 class Master
20 {
21 public:
22     virtual int eightSwordKill()
23     {
24         int ret = 8;
25         
26         cout << "Master::eightSwordKill() : " << ret << endl;
27         
28         return ret;
29     }
30 };
31 
32 class NewMaster : public Master
33 {
34 public:
35     int eightSwordKill()  // 重寫八劍齊飛
36     {
37         int ret = Master::eightSwordKill() * 2;
38         
39         cout << "NewMaster::eightSwordKill() : " << ret << endl;
40         
41         return ret;
42     }
43 };
44 
45 void field_pk(Master* master, Boss* boss)
46 {
47     int k = master->eightSwordKill();  // 賦值相容性加上函數重載,根據實際的對象調用函數;
48     int b = boss->fight();
49     
50     if( k < b )
51     {
52         cout << "Master is killed..." << endl;
53     }
54     else
55     {
56         cout << "Boss is killed..." << endl;
57     }
58 }
59 
60 int main()
61 {
62     Master master;
63     Boss boss;
64     
65     cout << "Master vs Boss" << endl;
66     
67     field_pk(&master, &boss);
68     
69     cout << "NewMaster vs Boss" << endl;
70     
71     NewMaster newMaster;
72     
73     field_pk(&newMaster, &boss);
74     
75     return 0;
76 }

   

10,小結:

    1,函數重寫只可能發生在父類與子類之間;

    2,根據實際對象的類型確定調用的具體函數;

    3,virtual 關鍵字是 C++ 中支持多態的唯一方式;

    4,被重寫的虛函數課表現出多態的特性;

   5,虛函數和多態的關係:

       1,多態是面向對象理論當中的一個概念,它和具體的程式設計語言是沒有關係的,也就是說多態指的僅僅是相同的行為方式,不同的行為結果;

       2,這種多態的表現形式在 C++ 中由虛函數來實現;


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 0基礎、非電腦專業怎麼學Python?其中最重要的,我想就是基礎的夯實。掌握好Python語法等基礎知識,才能在做項目時事半功倍。今天我們就來看看2位前輩是怎麼自學Python的。希望對你有所幫助。 ...
  • 1.二維矩陣的轉置 2.矩陣相加,A,B矩陣均需要為一個N*M的矩陣,即相加矩陣的行和列必須相等 3.矩陣相乘,A,B矩陣需要滿足條件為A為m*n的矩陣,B為n*p的矩陣,結果C為m*p的矩陣 4.編寫函數利用三項式壓縮稀疏矩陣稀疏矩陣:一個矩陣的大部分元素為0,則是稀疏矩陣 三項式:非零項用(i, ...
  • 所屬網站分類: 面試經典 > python 作者:外星人入侵 鏈接: http://www.pythonheidong.com/blog/article/13/ 來源:python黑洞網 www.pythonheidong.com webbrowser模塊提供了一個高級介面來顯示基於Web的文檔,大 ...
  • 積跬步,行千里,先從最簡單的開始寫。 這一篇介紹V8中的時間模塊,與libuv粗糙的update_loop_time方法不同,V8有一套獨立完整的類負責管理時間。 該類位於src/base/platform/time.h,是一個輔助模塊,首先來看一下繼承樹。 整個模塊的繼承關係比較簡單,一般常用的就 ...
  • 統計字元串中每一個不同的字元 JDK9的新特性: List介面,Set介面,Map介面裡邊增加了一個靜態方法of,可以給集合一次性添加多個元素 使用前提:當集合中存儲的元素的個數已經確定了,不再改變使用,也就是說,添加完元素之後,就不能再使用put方法來添加元素了 註意事項: 1. of方法只適用於 ...
  • 伺服器免密登錄 由於有多台伺服器,每次登錄還需要 去找對應的伺服器地址,然後輸入密碼,為了避免麻煩,就使用了免密登錄。普通登錄方式: ssh -p 22 [email protected] 每次登錄還需要輸入密碼,比較麻煩 更換免密碼登錄: 本地操作: 本地的公鑰位置: ~/.ssh/i... ...
  • 今天工作的時候接觸到客戶的一臺伺服器,業務邏輯比較簡單 。估算pv在120w左右吧,用的是阿裡雲2c4g的伺服器。一大早就開始卡頓了,登陸伺服器後查看負載到了八九十。 之後就想辦法調整一下吧。突然想起某位前輩說過的:開啟opcache吧,真的會變快的。 於是我馬上就開始整,過程很簡單 1.進入php ...
  • 對於Java初學者,可能會面對這麼一個問題,Java環境的配置,那麼廢話少說,直接開始。首先找到jdk的安裝包(我這邊以jdk1.8為例),雙擊安裝。 到這邊我們的jdk已經成功安裝,但這樣我們有些同學的eclipse依然沒法使用,那是因為eclipse需要配置jdk才能正常使用,下麵開始配置jdk ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...