最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++之多態(tài)(內(nèi)容不錯)

 更新時間:2020年01月30日 21:08:50   作者:熊二不二  
什么是多態(tài)?顧名思義就是同一個事物在不同場景下的多種形態(tài),需要的朋友可以參考下

編譯環(huán)境:WIN10 VS2017

這篇博客有點長,但都是滿滿的干貨,一定要看到最后,那才是重點。

什么是多態(tài)?

顧名思義就是同一個事物在不同場景下的多種形態(tài)。

這里寫圖片描述 

下面會具體的詳細的介紹。

靜態(tài)多態(tài)

我們以前說過的函數(shù)重載就是一個簡單的靜態(tài)多態(tài)

int Add(int left, int right)
{
 return left + right;
}
double Add(double left, int right)
{
 return left + right;
}

int main()
{
 Add(10, 20);
 //Add(10.0, 20.0); //這是一個問題代碼
 Add(10.0,20); //正常代碼
 return 0;
}

這里寫圖片描述 

可以看出來,靜態(tài)多態(tài)是編譯器在編譯期間完成的,編譯器會根據(jù)實參類型來選擇調(diào)用合適的函數(shù),如果有合適的函數(shù)可以調(diào)用就調(diào),沒有的話就會發(fā)出警告或者報錯。。。比較簡單,不做多介紹。

這里寫圖片描述

動態(tài)多態(tài)

什么是動態(tài)多態(tài)呢?
動態(tài)多態(tài): 顯然這和靜態(tài)多態(tài)是一組反義詞,它是在程序運行時根據(jù)基類的引用(指針)指向的對象來確定自己具體該調(diào)用哪一個類的虛函數(shù)。

我在西安臨潼上學(xué),我就以這邊的公交車舉個栗子?。?/p>

class TakeBus
{
public:
 void TakeBusToSubway()
 {
  cout << "go to Subway--->please take bus of 318" << endl;
 }
 void TakeBusToStation()
 {
  cout << "go to Station--->pelase Take Bus of 306 or 915" << endl;
 }
};
//知道了去哪要做什么車可不行,我們還得知道有沒有這個車
class Bus
{
public:
 virtual void TakeBusToSomewhere(TakeBus& tb) = 0; //???為什么要等于0
};

class Subway:public Bus
{
public:
 virtual void TakeBusToSomewhere(TakeBus& tb)
 {
  tb.TakeBusToSubway();
 }
};
class Station :public Bus
{
public:
 virtual void TakeBusToSomewhere(TakeBus& tb)
 {
  tb.TakeBusToStation();
 }
};

int main()
{
 TakeBus tb;
 Bus* b = NULL;
 //假設(shè)有十輛公交車,如果是奇數(shù)就是去地鐵口的,反之就是去火車站的
 for (int i = 1; i <= 10; ++i)
 {
  if ((rand() % i) & 1)
   b = new Subway;
  else
   b = new Station;
 }
 b->TakeBusToSomewhere(tb);
 delete b;
 return 0;
}

這就是一個簡單的動態(tài)多態(tài)的例子,它是在程序運行時根據(jù)條件去選擇調(diào)用哪一個函數(shù)。
而且,從上面的例子我們還發(fā)現(xiàn)了我在每一個函數(shù)前都加了virtual這個虛擬關(guān)鍵字,想想為什么?如果不加會不會構(gòu)成多態(tài)呢?
干想不如上機實踐:

class Base
{
public:
 virtual void Funtest1(int i)
 {
  cout << "Base::Funtest1()" << endl;
 }
 void Funtest2(int i)
 {
  cout << "Base::Funtest2()" << endl;
 }
};
class Drived :public Base
{
 virtual void Funtest1(int i)
 {
  cout << "Drived::Fubtest1()" << endl;
 }
 virtual void Funtest2(int i)
 {
  cout << "Drived::Fubtest2()" << endl;
 }
 void Funtest2(int i)
 {
  cout << "Drived::Fubtest2()" << endl;
 }
};
void TestVirtual(Base& b)
{
 b.Funtest1(1);
 b.Funtest2(2);
}
int main()
{
 Base b;
 Drived d;
 TestVirtual(b);
 TestVirtual(d);
 return 0;
}

這里寫圖片描述 

在調(diào)用FuncTest2的時候我們看出來他并沒有給我們調(diào)用派生類的函數(shù),因此我們可以對動態(tài)多態(tài)的實現(xiàn)做個總結(jié)。

動態(tài)多態(tài)的條件:

●基類中必須包含虛函數(shù),并且派生類中一定要對基類中的虛函數(shù)進行重寫。
●通過基類對象的指針或者引用調(diào)用虛函數(shù)。

重寫 :

(a)基類中將被重寫的函數(shù)必須為虛函數(shù)(上面的檢測用例已經(jīng)證實過了)
(b)基類和派生類中虛函數(shù)的原型必須保持一致(返回值類型,函數(shù)名稱以及參數(shù)列表),協(xié)變和析構(gòu)函數(shù)(基類和派生類的析構(gòu)函數(shù)是不一樣的)除外
(c)訪問限定符可以不同
那么問題又來了,什么是協(xié)變?
協(xié)變:基類(或者派生類)的虛函數(shù)返回基類(派生類)的指針(引用)
總結(jié)一道面試題:那些函數(shù)不能定義為虛函數(shù)?
經(jīng)檢驗下面的幾個函數(shù)都不能定義為虛函數(shù):
1)友元函數(shù),它不是類的成員函數(shù)
2)全局函數(shù)
3)靜態(tài)成員函數(shù),它沒有this指針
3)構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),以及賦值運算符重載(可以但是一般不建議作為虛函數(shù))

抽象類:

在前面公交車的例子上我提了一個問題:

class Bus
{
public:
 virtual void TakeBusToSomewhere(TakeBus& tb) = 0; //???為什么要等于0
};

在成員函數(shù)(必須為虛函數(shù))的形參列表后面寫上=0,則成員函數(shù)為純虛函數(shù)。包含純虛函數(shù)的類叫做抽象類(也叫接口類),抽象類不能實例化出對象。純虛函數(shù)在派生類中重新定義以后,派生類才能實例化出對象。純虛函數(shù)是一定要被繼承的,否則它存在沒有任何意義。

這里寫圖片描述

多態(tài)調(diào)用原理

class Base
{
public:
 virtual void Funtest1(int i)
 {
  cout << "Base::Funtest1()" << endl;
 }
 virtual void Funtest2(int i)
 {
  cout << "Base::Funtest2()" << endl;
 }
 int _data;
};

int main()
{
 cout << sizeof(Base) << endl;
 Base b;
 b._data = 10;
 return 0;
}

這里寫圖片描述 

8?不知道大家有沒有問題,反正我是有疑惑了。以前在對象模型(https://blog.csdn.net/qq_39412582/article/details/80808754)時我提到過怎么來求一個類的大小。按照那個方法,這里應(yīng)該是4才對啊,為什么會是8呢?

通過觀察。我們發(fā)現(xiàn)這個例子里面和以前不一樣,類成員函數(shù)變成了虛函數(shù),這是不是引起類大小變化的原因呢?
我們假設(shè)就是這樣,然后看看內(nèi)存里是怎么存儲的呢?

這里寫圖片描述 

可以看到它在內(nèi)存里多了四個字節(jié),那這四個字節(jié)的內(nèi)容到底是什么呢?

這里寫圖片描述

是不是有點看不懂,我們假設(shè)它是一個地址去看地址里存的東西的時候發(fā)現(xiàn)它存的是兩個地址。
我假設(shè)它是虛函數(shù)的地址,我們來驗證一下:

typedef void (__stdcall *PVFT)(); //函數(shù)指針
int main()
{
 cout << sizeof(Base) << endl;
 Base b;
 b._data = 10;
 PVFT* pVFT = (PVFT*)(*((int*)&b));
 while (*pVFT)
 {
  (*pVFT)();
  pVFT+=1;
 }
 return 0;
}

這里寫圖片描述 

結(jié)果好像和我們的猜想一樣,是一件開心的事。然后我給一張圖總結(jié)一下:

這里寫圖片描述 

在反匯編中我們還可以看到,如果含有虛函數(shù)的類中沒有定義構(gòu)造函數(shù),編譯器會自動合成一個構(gòu)造函數(shù)

這里寫圖片描述

這里寫圖片描述

對于派生類的東西我給個鏈接仔細看,人家總結(jié)的超級贊,我偷個懶就不寫了,老鐵們包容下啊。

派生類虛表:

1.先將基類的虛表中的內(nèi)容拷貝一份
2.如果派生類對基類中的虛函數(shù)進行重寫,使用派生類的虛函數(shù)替換相同偏移量位置的基類虛函數(shù)
3.如果派生類中新增加自己的虛函數(shù),按照其在派生類中的聲明次序,放在上述虛函數(shù)之后

https://coolshell.cn/articles/12176.html

多態(tài)缺陷

●降低了程序運行效率(多態(tài)需要去找虛表的地址)
●空間浪費

相關(guān)文章

  • C++實現(xiàn)簡易的彈球小游戲

    C++實現(xiàn)簡易的彈球小游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡易的彈球小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 解析C++編程中的選擇結(jié)構(gòu)和switch語句的用法

    解析C++編程中的選擇結(jié)構(gòu)和switch語句的用法

    這篇文章主要介紹了解析C++編程中的選擇結(jié)構(gòu)和switch語句的用法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • 用c++實現(xiàn)將文本每個單詞首字母轉(zhuǎn)換為大寫

    用c++實現(xiàn)將文本每個單詞首字母轉(zhuǎn)換為大寫

    本篇文章是對用c++實現(xiàn)將文本每個單詞首字母轉(zhuǎn)換為大寫的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • c++實現(xiàn)堆排序的示例代碼

    c++實現(xiàn)堆排序的示例代碼

    本文主要介紹了c++實現(xiàn)堆排序的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • c++臨時對象導(dǎo)致的生命周期問題

    c++臨時對象導(dǎo)致的生命周期問題

    對象的生命周期是c++中非常重要的概念,它直接決定了你的程序是否正確以及是否存在安全問題,這篇文章主要介紹了c++臨時對象導(dǎo)致的生命周期問題 ,需要的朋友可以參考下
    2024-07-07
  • 詳解C語言的預(yù)處理效果

    詳解C語言的預(yù)處理效果

    這篇文章主要為大家介紹了C語言的預(yù)處理效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++類中的特殊成員函數(shù)示例詳解

    C++類中的特殊成員函數(shù)示例詳解

    這篇文章主要給大家介紹了關(guān)于C++類中特殊成員函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Qt實現(xiàn)網(wǎng)絡(luò)聊天室的示例代碼

    Qt實現(xiàn)網(wǎng)絡(luò)聊天室的示例代碼

    本文主要介紹了Qt實現(xiàn)網(wǎng)絡(luò)聊天室,實現(xiàn)一個在線聊天室, 使用tcp對客戶端和服務(wù)器端進行通訊。具有一定的參考價值,具有一定的參考價值,
    2021-06-06
  • C語言?使用qsort函數(shù)來進行快速排序

    C語言?使用qsort函數(shù)來進行快速排序

    排序方法有很多種:選擇排序,冒泡排序,歸并排序,快速排序等。?看名字都知道快速排序是目前公認的一種比較好的排序算法。因為他速度很快,所以系統(tǒng)也在庫里實現(xiàn)這個算法,便于我們的使用。?這就是qsort函數(shù)
    2022-02-02
  • C++畫正弦線實例代碼

    C++畫正弦線實例代碼

    這篇文章主要介紹了C++畫正弦線實例代碼,是C++圖形操作程序設(shè)計中比較常見的一個技巧,需要的朋友可以參考下
    2014-10-10

最新評論

太保市| 北辰区| 当涂县| 广灵县| 黑龙江省| 图们市| 蕲春县| 崇文区| 霍州市| 永修县| 麦盖提县| 金溪县| 合作市| 分宜县| 和龙市| 高邑县| 拉萨市| 北流市| 肥乡县| 河东区| 巩义市| 化德县| 华阴市| 大埔县| 航空| 自贡市| 定襄县| 内江市| 墨江| 新干县| 开原市| 周宁县| 南城县| 玉林市| 祁东县| 日土县| 合水县| 大安市| 扎鲁特旗| 凤凰县| 桐庐县|