中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

C++運(yùn)行期多態(tài)和編譯期多態(tài)(以不同的模板參數(shù)調(diào)用不同的函數(shù))

2021-02-06    分類: 網(wǎng)站建設(shè)

在面向?qū)ο驝++編程中,多態(tài)是OO三大特性之一,這種多態(tài)稱為運(yùn)行期多態(tài),也稱為動(dòng)態(tài)多態(tài);在泛型編程中,多態(tài)基于template(模板)的具現(xiàn)化與函數(shù)的重載解析,這種多態(tài)在編譯期進(jìn)行,因此稱為編譯期多態(tài)或靜態(tài)多態(tài)。

該類對(duì)象安插一個(gè)虛函數(shù)表指針,并為類(基類和派生類)設(shè)置虛函數(shù)表,虛函數(shù)表中存放的是該類虛函數(shù)地址。同時(shí),改寫虛函數(shù)調(diào)用代碼(函數(shù)指針調(diào)用)。運(yùn)行期間通過虛函數(shù)表指針與虛函數(shù)表去確定該類虛函數(shù)的真正實(shí)現(xiàn)。

#include
using namespace std;
class Animal
{
public :virtual void shout() = 0;
};
class Dog :public Animal
{
public:virtual void shout(){ cout << "汪汪!"<shout();//虛函數(shù)的調(diào)用會(huì)被編譯器轉(zhuǎn)換為對(duì)虛函數(shù)表的訪問Cat cat;// ② 編譯器會(huì)為每個(gè)新建對(duì)象添加一函數(shù)指針,指向虛函數(shù)表animal = &cat;animal->shout();//animal代表this指針,shout是虛函數(shù)// ③ 編譯器會(huì)改寫對(duì)象調(diào)用成員函數(shù)代碼,改寫成指針調(diào)用的形式Animal * anim3 = new Bird;anim3->shout();delete anim3;system("pause");return 0;
}
/*
汪汪!
喵喵~
嘰喳!
*/

編譯器會(huì)構(gòu)建一張?zhí)摫恚?vtable ),每一個(gè)類都有自己獨(dú)特的虛表。同時(shí),在這個(gè)繼承鏈上,編譯器會(huì)為基類插入一個(gè)隱式的指針(一般是對(duì)象的首地址),指向虛表,稱為__vptr。然后,子類繼承父類時(shí),會(huì)獲得繼承下來的__vptr,再根據(jù)自己的類的情況兼容(修改虛函數(shù)表里的值、發(fā)生偏移等。于是,當(dāng)我們構(gòu)建具體的類時(shí),若是基類類型,__vptr就會(huì)指向父類的vtable,若是子類類型,__vptr就會(huì)指向子類的vtable。


下面再看一個(gè)實(shí)例來了解虛函數(shù)表,及對(duì)象的函數(shù)指針是如何指向虛函數(shù)表以及調(diào)用虛函數(shù)代碼是如何改寫的?

#include 
using namespace std;
class A
{
public:
 A(int _a1 = 1) : a1(_a1) { }
 virtual void f() { cout << "A::f" << endl; }
 virtual void g() { cout << "A::g" << endl; }
 virtual void h() { cout << "A::h" << endl; }
 ~A() {}
private:
 int a1;
};
class C : public A
{
public:
 C(int _a1 = 1, int _c = 4) :A(_a1), c(_c) { }
 virtual void f() { cout << "C::f" << endl; }
 virtual void g() { cout << "C::g" << endl; }
 virtual void h() { cout << "C::h" << endl; }
private:
 int c;
};
// 通過訪問類對(duì)象的前4字節(jié)(32位編譯器)找到虛函數(shù)表。
// 虛函數(shù)表最后一項(xiàng)用的是0,代表虛函數(shù)表結(jié)束。
typedef void(*FUNC)(); //重定義函數(shù)指針,指向函數(shù)的指針
void PrintVTable(long* vTable) //訪問虛函數(shù)表
{
 if (vTable == NULL)
 {
 return;
 }
 cout << "vtbl:" << vTable << endl;
 int i = 0;
 for (; vTable[i] != 0; ++i)
 {
 printf("function : %d :0X%x->", i, vTable[i]);
 FUNC f = (FUNC)vTable[i];
 f(); //訪問虛函數(shù)
 }
 cout << endl;
}
void main()
{A a1;long *p = (long *)(*(long*)&a1);PrintVTable(p);C c;long *p2 = (long *)(*(long*)&c);PrintVTable(p2);system("pause");
}
/*
vtbl:00471048
function : 0 :0X40105a->A::f
function : 1 :0X4012c6->A::g
function : 2 :0X4010b9->A::h
vtbl:00471070
function : 0 :0X4010eb->C::f
function : 1 :0X4011d1->C::g
function : 2 :0X401280->C::h
*/

不同的推斷結(jié)果調(diào)用不同的函數(shù),這就是編譯器多態(tài)。這類似于重載函數(shù)在編譯器進(jìn)行推導(dǎo),以確定哪一個(gè)函數(shù)被調(diào)用。

3 運(yùn)行期多態(tài)與編譯期多態(tài)優(yōu)缺點(diǎn)分析

3.1 運(yùn)行期多態(tài)優(yōu)點(diǎn)

OO設(shè)計(jì)中重要的特性,對(duì)客觀世界直覺認(rèn)識(shí)。

能夠處理同一個(gè)繼承體系下的異質(zhì)類集合。

3.2 運(yùn)行期多態(tài)缺點(diǎn)

運(yùn)行期間進(jìn)行虛函數(shù)綁定,提高了程序運(yùn)行開銷。

龐大的類繼承層次,對(duì)接口的修改易影響類繼承層次。

由于虛函數(shù)在運(yùn)行期在確定,所以編譯器無法對(duì)虛函數(shù)進(jìn)行優(yōu)化。

虛表指針增大了對(duì)象體積,類也多了一張?zhí)摵瘮?shù)表,當(dāng)然,這是理所應(yīng)當(dāng)值得付出的資源消耗,列為缺點(diǎn)有點(diǎn)勉強(qiáng)。

3.3 編譯期多態(tài)優(yōu)點(diǎn)

它帶來了泛型編程的概念,使得C++擁有泛型編程與STL這樣的強(qiáng)大武器。

在編譯器完成多態(tài),提高運(yùn)行期效率。

具有很強(qiáng)的適配性與松耦合性,對(duì)于特殊類型可由模板偏特化、全特化來處理。

3.4 編譯期多態(tài)缺點(diǎn)

程序可讀性降低,代碼調(diào)試帶來困難。

無法實(shí)現(xiàn)模板的分離編譯,當(dāng)工程很大時(shí),編譯時(shí)間不可小覷。

無法處理異質(zhì)對(duì)象集合。

文章標(biāo)題:C++運(yùn)行期多態(tài)和編譯期多態(tài)(以不同的模板參數(shù)調(diào)用不同的函數(shù))
當(dāng)前地址:http://www.rwnh.cn/news14/99414.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)、微信公眾號(hào)、ChatGPT搜索引擎優(yōu)化、品牌網(wǎng)站建設(shè)微信小程序

廣告

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

商城網(wǎng)站建設(shè)
永春县| 湟源县| 古浪县| 嘉兴市| 新建县| 大名县| 收藏| 神农架林区| 望奎县| 牟定县| 西吉县| 余干县| 石家庄市| 辉县市| 临洮县| 和田县| 河西区| 乌鲁木齐市| 曲麻莱县| 白沙| 平湖市| 安顺市| 保靖县| 桓仁| 伊川县| 武清区| 宾川县| 常山县| 白山市| 栖霞市| 平昌县| 日土县| 萍乡市| 仙桃市| 溆浦县| 秦皇岛市| 新绛县| 绥阳县| 桑植县| 北京市| 灌云县|