免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

C++運行期多態和編譯期多態(以不同的模板參數調用不同的函數)

2021-02-06    分類: 網站建設

在面向對象C++編程中,多態是OO三大特性之一,這種多態稱為運行期多態,也稱為動態多態;在泛型編程中,多態基于template(模板)的具現化與函數的重載解析,這種多態在編譯期進行,因此稱為編譯期多態或靜態多態。

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

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

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


下面再看一個實例來了解虛函數表,及對象的函數指針是如何指向虛函數表以及調用虛函數代碼是如何改寫的?

#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;
};
// 通過訪問類對象的前4字節(32位編譯器)找到虛函數表。
// 虛函數表最后一項用的是0,代表虛函數表結束。
typedef void(*FUNC)(); //重定義函數指針,指向函數的指針
void PrintVTable(long* vTable) //訪問虛函數表
{
 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(); //訪問虛函數
 }
 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
*/

不同的推斷結果調用不同的函數,這就是編譯器多態。這類似于重載函數在編譯器進行推導,以確定哪一個函數被調用。

3 運行期多態與編譯期多態優缺點分析

3.1 運行期多態優點

OO設計中重要的特性,對客觀世界直覺認識。

能夠處理同一個繼承體系下的異質類集合。

3.2 運行期多態缺點

運行期間進行虛函數綁定,提高了程序運行開銷。

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

由于虛函數在運行期在確定,所以編譯器無法對虛函數進行優化。

虛表指針增大了對象體積,類也多了一張虛函數表,當然,這是理所應當值得付出的資源消耗,列為缺點有點勉強。

3.3 編譯期多態優點

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

在編譯器完成多態,提高運行期效率。

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

3.4 編譯期多態缺點

程序可讀性降低,代碼調試帶來困難。

無法實現模板的分離編譯,當工程很大時,編譯時間不可小覷。

無法處理異質對象集合。

文章標題:C++運行期多態和編譯期多態(以不同的模板參數調用不同的函數)
當前地址:http://m.newbst.com/news14/99414.html

成都網站建設公司_創新互聯,為您提供域名注冊微信公眾號ChatGPT搜索引擎優化品牌網站建設微信小程序

廣告

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

商城網站建設