欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

【C++】動(dòng)態(tài)多態(tài)-創(chuàng)新互聯(lián)

多態(tài)【Polymorphism】是面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)重要特性,即一個(gè)接口,多種實(shí)現(xiàn)方式。

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)鳩江免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了近1000家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

在C++中,多態(tài)體現(xiàn)為兩個(gè)方面,一個(gè)是編譯時(shí)多態(tài),一個(gè)是運(yùn)行時(shí)多態(tài)。編譯時(shí)多態(tài)是靜態(tài)多態(tài),運(yùn)行時(shí)時(shí)動(dòng)態(tài)多態(tài)。

靜態(tài)多態(tài)分為【函數(shù)重載】和【模板(也稱為泛型編程)】。

函數(shù)重載主要是C++ 將參數(shù)列表也作為函數(shù)的標(biāo)識(shí),不想C,只是將函數(shù)名作為標(biāo)識(shí)。那么就存在最佳匹配問題。

運(yùn)行時(shí)多態(tài)主要指【虛函數(shù)】

虛函數(shù):
在基類聲明一個(gè)虛函數(shù),在子類中進(jìn)行重寫。基類的引用或者指針是指向派生類的對(duì)象的,基類調(diào)用該函數(shù)時(shí),自動(dòng)指向派生類的函數(shù),這就是動(dòng)態(tài)多態(tài)。

注意:如果不聲明一個(gè)虛函數(shù),那么就是【函數(shù)隱藏/覆蓋】,注意這里是子類和父類擁有同名函數(shù),而無需考慮參數(shù)列表。

具體實(shí)現(xiàn)
每個(gè)有虛函數(shù)的類都會(huì)有一個(gè)虛函數(shù)表,這里保存的就是虛函數(shù)的地址信息。所有存在虛函數(shù)的類的實(shí)例都會(huì)在內(nèi)存中保存一個(gè)虛函數(shù)表,當(dāng)調(diào)用虛函數(shù)的時(shí)候,從虛函數(shù)表中查找對(duì)應(yīng)的需要調(diào)用的函數(shù)地址。

編譯器會(huì)為每個(gè)存在虛函數(shù)的類對(duì)象插入一個(gè)vtpr(virtul function pointer),該vptr指向存放了虛函數(shù)地址的虛函數(shù)表vtbl,這樣對(duì)象在調(diào)用虛函數(shù)的時(shí)候,第一步會(huì)先根據(jù)vptr找到vbtl,然后根據(jù)該虛函數(shù)在vbtl中的索引來進(jìn)行調(diào)用,這樣就實(shí)現(xiàn)了運(yùn)行時(shí)多態(tài)功能。

大部分編譯器的實(shí)現(xiàn),都是將vptr放在對(duì)象的首位,所以我們可以通過這個(gè)特點(diǎn)來直接調(diào)用虛函數(shù)表中的函數(shù)。

Derived d;
long address = *(long*)&d;
Fun fun= (Fun)(*(long*)address);

對(duì)比普通成員函數(shù)和虛函數(shù)
在C++中,允許對(duì)函數(shù)進(jìn)行重載,那么就需要對(duì)函數(shù)進(jìn)行name mangling。

在此,說下編譯器mangling后函數(shù)名的規(guī)則,仍然以成員函數(shù)Print()優(yōu)化后的名稱_ZN4Base5PrintEv為例(這個(gè)規(guī)則以筆者使用的gcc為例):

  • 編碼后的符號(hào)由_Z開頭
  • 如果有作用域符,則在_Z之后加上N
  • 接著是命名空間名字長(zhǎng)度、命名空間名字、類名字長(zhǎng)度、類名、成員函數(shù)名稱、函數(shù)名稱
  • 如果有作用域符,則以E結(jié)尾
  • 最后加上函數(shù)形參符號(hào),void是v,int是i,char是c,P代表指針,有幾個(gè)形參就寫幾個(gè)符號(hào)

從上述規(guī)則我們可以看出,C++中的重載只跟函數(shù)名和函數(shù)參數(shù)有關(guān)。

而對(duì)于成員函數(shù),會(huì)將其轉(zhuǎn)化成對(duì)應(yīng)的非成員函數(shù):
#1 安插一個(gè)額外的參數(shù),const class *this 進(jìn)入成員函數(shù)
#2 將成員函數(shù)進(jìn)行mangling 處理,轉(zhuǎn)換成獨(dú)一無二的函數(shù)名
最終會(huì)被轉(zhuǎn)化成一個(gè)普通的函數(shù)。

而虛函數(shù)對(duì)比普通的成員函數(shù),多了一步虛函數(shù)尋址。
不過基類指針指向什么具體類型,但是總可以找到對(duì)應(yīng)對(duì)象的vtbl,就可以進(jìn)行函數(shù)訪問。

C++17中引入了 variant 和 visit 以實(shí)現(xiàn)多態(tài)

variant是C++17引入的變體類型,它大的優(yōu)勢(shì)是提供了一種新的具有多態(tài)性的處理不同類型集合的方法。也就是說,它可以幫助我們處理不同類型的數(shù)據(jù),并且不需要公共基類和指針。

可以將其理解為union的升級(jí)版,之所以稱之為升級(jí)版,是因?yàn)閡nion有如下缺點(diǎn):

  • 對(duì)象并不知道它們現(xiàn)在持有的值的類型
  • 不能持有std::string等非平凡類型
  • 不能被繼承

既然稱之為union的升級(jí)版,那么union的缺點(diǎn)其肯定不存在的,在此我們整理了下variant的特點(diǎn):

  • 可以獲取當(dāng)前類型
  • 可以持有任何類型的值(不能是引用、C類型的數(shù)組指針、void等)
  • 可以被繼承

【visit】
定義:

templateconstexpr visit( Visitor&& vis, Variants&&... vars );

在上述定義中,vis是一個(gè)訪問器,而vars則是傳給訪問器的參數(shù)列表。換句話說,std::visit能將所有變體類型參數(shù)所存放的數(shù)據(jù)作為參數(shù)傳給函數(shù)。

std::visit訪問器可以是函數(shù)對(duì)象、泛型lambda以及重載的lambda等。

#include#include#includestruct Visitor {void operator()(int n) const {std::cout<< "int: "<< n<< std::endl;
  }
  
  void operator()(const std::string &str) const {std::cout<< "string: "<< str<< std::endl;
  }
};
  
int main() {std::variantv;
  Visitor vst;
  v = "with Visitor";
  std::visit(vst, v);
  return 0;
}

輸入如下:

string:with Visitor

結(jié)合variant 和 visit 實(shí)現(xiàn)多態(tài)

struct CallPrint {void operator()(const Base& b) {b.Print(); }    
    void operator()(const Derived& d) {d.Print(); }    
};

int main() {std::variantv = Derived();
  std::visit(CallPrint{}, v);
  v = Base();
  std::visit(CallPrint{}, v);
  return 0;
}

這就需要從其優(yōu)缺點(diǎn)來進(jìn)行分析,使用者可以根據(jù)其特點(diǎn)進(jìn)行選擇,首先,總結(jié)下其優(yōu)點(diǎn):

  • 值語義,無需動(dòng)態(tài)分配
  • 不需要基類,類之間可以不相關(guān)
  • 相比于虛函數(shù)的重載(函數(shù)名、參數(shù)完全一致),variant只需要函數(shù)名一致即可,即不同的類里面可以函數(shù)名相同而參數(shù)不同,通過visit來進(jìn)行對(duì)應(yīng)的調(diào)用,從而實(shí)現(xiàn)多態(tài)

看完了前面的內(nèi)容,其缺點(diǎn)也相對(duì)來說比較明顯,如下:

  • 需要在編譯時(shí)預(yù)先了解所有類型
  • 浪費(fèi)內(nèi)存,因?yàn)閟td::variant大小是支持類型的大大小。因此,如果一種類型是 10 字節(jié),另一種是100 字節(jié),那么每個(gè)變體至少是 100 字節(jié)。因此,您可能會(huì)丟失 90 個(gè)字節(jié)
  • 每個(gè)多態(tài)操作都需要實(shí)現(xiàn)一個(gè)對(duì)應(yīng)的visit

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)站欄目:【C++】動(dòng)態(tài)多態(tài)-創(chuàng)新互聯(lián)
地址分享:http://chinadenli.net/article16/dihcgg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)企業(yè)建站App設(shè)計(jì)網(wǎng)頁設(shè)計(jì)公司手機(jī)網(wǎng)站建設(shè)網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管