日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 虚函数,纯虚函数的本质区别

發布時間:2023/12/2 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 虚函数,纯虚函数的本质区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載博客:https://mp.weixin.qq.com/s?__biz=MzAxNzYzMTU0Ng==&mid=2651289202&idx=1&sn=431ffd1fae4823366a50b68aed2838d4&chksm=80114627b766cf31f72018ef5f1fe29591e9f6f4bd72018e7aea849342ca6f0a271fb38465ae#rd

?

學習C++的多態性,你必然聽過虛函數的概念,你必然知道有關她的種種語法,但你未必了解她為什么要那樣做,未必了解她種種行為背后的所思所想。深知你不想在流于表面語法上的蜻蜓點水似是而非,今天我們就一起來揭開擋在你和虛函數(女神)之間的這一層窗戶紙。

?

?

首先,我們要搞清楚女神的所作所為,即語法規范。然后再去探究她背后的邏輯道理。她的語法說來也不復雜,概括起來就這么幾條:

?

  • 在類成員方法的聲明(不是定義)語句前面加個單詞:virtual,她就會搖身一變成為虛函數。

  • 在虛函數的聲明語句末尾中加個 =0 ,她就會搖身一變成為純虛函數。

  • 子類可以重新定義基類的虛函數,我們把這個行為稱之為復寫override)。

  • 不管是虛函數還是純虛函數,基類都可以為提供他們的實現implementation),如果有的話子類可以調用基類的這些實現。

  • 子類可自主選擇是否要提供一份屬于自己的個性化虛函數實現。

  • 子類必須提供一份屬于自己的個性化純虛函數實現。

    ?

  • ?

    語法都列出來了,背后的邏輯含義是什么呢?我們用一個生動的例子來說明,虛函數是如何實現多態性的。

    ?

    假設我們要設計關于飛行器的類,并且提供類似加油、飛行的實現代碼,考慮具體情況,飛行器多種多樣,有民航客機、殲擊機、轟炸機、直升機、熱氣球、火箭甚至竄天猴、孔明燈、紙飛機!

    假設我們有一位牛得一比的飛行員,他能給各式各樣的飛行器加充不同的燃料,也能駕駛各式各樣的飛行器。下面我們來看看這些類可以怎么設計。

    首先,飛行器。由于我們假設所有的飛行器都有兩種行為:加油飛行。因此我們可以將這兩種行為抽象到一個基類中,并由它來派生具體的某款飛行器。

    ?

    這是一個描述飛行器的基類,提供了兩個基本的功能:加油和飛行

    class aircraft

    {

    ? ? void refuel(); // 加燃油,普通虛函數

    ? ? void fly()=0; ?// 飛行,純虛函數

    };

    ?

    這是一個普通虛函數,意味著基類希望子類提供自己的個性化實現代碼,但基類同時也提供一個缺省的虛函數實現版本,在子類不復寫該虛函數的情況下作為備選方案

    void aircraft::refuel()

    {

    ? ? // 加充通用型燃油

    }

    ?

    這是一個純虛函數,意味著基類強制子類必須提供自己的個性化版本,否則編譯將失敗。但讓人驚奇的是,C++仍然保留了基類提供該純虛函數代碼實現的權利,這也許是給千變萬化的實際情況留下后路

    void aircraft::fly()

    {

    ? ? // 一種不應該被使用的缺省飛行方案

    }

    ?

    有了基類aircraft,我們就可以瀟灑地派生出各式各樣的飛行器了,比如轟炸機直升機

    轟炸機類定義,復寫了加油和飛行

    class?bomber : public aircraft

    {

    ? ? void refuel(){} // 加充轟炸機的特殊燃油!

    ? ? void fly(){} // 轟炸機實彈飛行!

    };

    ?

    直升機類定義,復寫了飛行代碼,但沒有復寫加油

    class?copter: public aircraft

    {

    ? ? void fly(){} // 直升機盤旋!

    };

    ?

    以上代碼可以看到,直升機類(copter)沒有自己的加油方式,直接使用了基類提供的缺省加油的方式。此時我們來定義一個能駕馭多機型的王牌飛行員類:

    ?

    一個能王牌飛行員

    class pilot

    {

    ? ? void refuelPlane(aircraft *p);

    ? ? void dirvePlane(aircraft *p);

    };

    ?

    給我什么飛機我就加什么油

    void pilot::refuelPlane(aircraft *p)

    {

    ? ? p->refuel();

    }

    ?

    給我什么飛機我就怎么飛

    void pilot::dirvePlane(aircraft *p)

    {

    ? ? p->fly();

    }

    ?

    很明顯,我們接下來要給這位很浪的飛行員表演一下操縱各種飛行器的機會,我們來定義各種飛機然后丟給他去處理

    ?

    定義兩架飛機,一架轟6K,一架武直10

    aircraft *H6K = new bomber;

    aircraft *WZ10?= new copter;

    ?

    來一個王牌飛行員,給H6K加油(加的是轟炸機特殊燃油),并且按照H6K的特點飛行

    pilot Jack;

    Jack.refuelPlane(H6K); ?// 加充轟炸機燃油

    Jack.flyPlane(H6K); // 轟炸機實彈飛行

    ?

    給WZ10加油(加的是基類提供的通用燃油),按照WZ10的特點飛行

    Jack.refuelPlane(WZ10); // 加充通用型燃油

    Jack.flyPlane(WZ10); // 直升機盤旋

    ?

    上述代碼體現了最經典的所謂多態的場景,給Jack不同的飛機,就能表現不同的結果。虛函數和純虛函數都能做到這一點,區別是,子類如果不提供虛函數的實現,那就會自動調用基類的缺省方案。而子類如果不提供純虛函數的實現,則編譯將會失敗。基類提供的純虛函數實現版本,無法通過指向子類對象的基類類型指針或引用來調用,因此不能作為子類相應虛函數的備選方案。下面給出總結。

    ?

    ?

    第一,當基類的某個成員方法,在大多數情形下都應該由子類提供個性化實現,但基類也可以提供一個備選方案的時候,請將其設計為虛函數。例如飛行器的加油動作,每種不同的飛行器原則上都應該有自己的個性化的加充然后的方式,但也不免可以有一種通用的然后和加充方式。

    ?

    第二,當基類的某個成員方法,必須由子類提供個性化實現的時候,請將其設計為純虛函數。例如飛行器的飛行動作,邏輯上每種飛行器都必須提供為其特殊設計的個性化飛行行為,而不應該有任何一種“通用的飛行方式”。

    ?

    第三,使用一個基類類型的指針或者引用,來指向子類對象,進而調用經由子類復寫了的個性化的虛函數,這是C++實現多態性的一個最經典的場景

    ?

    第四,基類提供的純虛函數的實現版本,并非為了多態性考慮,因為指向子類對象的基類指針和引用無法調用該版本。純虛函數在基類中的實現跟多態性無關,它只是提供了一種語法上的便利,在變化多端的應用場景中留有后路

    ?

    第五,虛函數和普通的函數實際上是存儲在不同的區域的,虛函數所在的區域是可被覆蓋(也稱復寫override)的,每當子類定義相同名稱的虛函數時就將原來基類的版本給覆蓋了,另一側面也說明了為什么基類中聲明的虛函數在后代類中不需要另加聲明一律自動為虛函數,因為它所存儲的位置不會發生改變。而普通函數的存儲區域不會覆蓋,每個類都有自己獨立的區域互不相干。

    ?

    最后附一幅草圖以供參考

    轉載于:https://www.cnblogs.com/HPAHPA/p/8351284.html

    總結

    以上是生活随笔為你收集整理的c++ 虚函数,纯虚函数的本质区别的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。