virtual 虛函式補充

2021-09-19 12:31:59 字數 3751 閱讀 4377

class base

private:

int ma;};

class derived:public base};

intmain()

這裡分析一下p->show()的反彙編**

p->

show()

;//將p的裡面存的值放到eax暫存器, 這裡是derived物件的位址

00864b1d mov eax,dword ptr [p]

//將eax(derived) 裡面的值的前四個位元組(dword 雙字)的內容放到edx暫存器

//這裡是vfptr的值,因為該物件的前四個位元組是虛函式表的位址

00864b20 mov edx,dword ptr [eax]

//將esp 暫存器的內容放在 esi 暫存器

00864b22 mov esi,esp

//將p指向的位址存放在ecx中

00864b24 mov ecx,dword ptr [p]

//取出虛函式表的前四個位元組,(第乙個虛函式的位址)

00864b27 mov eax,dword ptr [edx]

//呼叫虛函式

00864b29 call eax

因為inline是將函式的**在呼叫處展開,不存在函式棧幀的開闢,更沒有函式位址,而虛函式表中儲存的是每個虛函式的位址,所以這裡的inline 是不起作用的。

靜態函式又叫類的成員方法,靜態成員函式的呼叫是不依賴物件的存在的,也就是在建立物件之前,就可以呼叫靜態成員函式。

而虛函式存在於虛函式表中,虛函式表在編譯階段生成,訪問虛函式的時候,首先在物件的前四個位元組中找到虛函式表的位址,然後在虛函式表中查詢相應的虛函式的位址所以說虛函式的訪問是依賴物件存在的而靜態成員方法不能依賴物件的存在,所以二者是不能相容的。

關於虛函式表於虛函式指標的內容參考

跟前面static 修飾的類似,如果建構函式可以是虛函式,那呼叫建構函式之前物件並不存在,即無法通過物件的vfptr 指標找到虛函式表的位址,也就無法訪問建構函式。

與死鎖的原理相似,只有呼叫建構函式才能產生物件,只有產生物件才能呼叫建構函式

通過上面的彙編**的分析,我們可以看到,動態繫結時呼叫函式的彙編指令是

call eax直接call 乙個 暫存器,而靜態繫結通常是call + 位址,這裡通過這個特徵看一下什麼時候動態繫結,什麼時候靜態繫結

int

main()

derived d;

00c34a41 call derived:

:derived (

0c31564h)

d.show()

;00c34a46 lea ecx,

[d]//通過物件呼叫是靜態繫結

00c34a49 call derived:

:show (

0c3155fh)

int

main()

p->

show()

;00f

84a7d mov eax,dword ptr [p]

00f84a80 mov edx,dword ptr [eax]

00f84a82 mov esi,esp

00f84a84 mov ecx,dword ptr [p]

00f84a87 mov eax,dword ptr [edx]

//動態繫結

00f84a89 call eax

這裡不一一測試,通過基類指標或引用,派生類指標或引用訪問都是動態繫結

通過物件訪問都是靜態繫結

前面說過虛函式的動態繫結依賴於物件的存在,建構函式結束之前物件還沒有存在,所以在建構函式中呼叫虛函式,應該是靜態繫結,這裡給出驗證

class base

virtual void

show()

private:

int ma;};

intmain()

//彙編指令

base p;

00974ace lea ecx,

[p]//這裡進入建構函式

00974ad1 call base:

:base (

097155ah)

/***********************建構函式中************************/

0097497f pop ecx

00974980 mov dword ptr [this]

,ecx

00974983 mov eax,dword ptr [this]

00974986 mov dword ptr [eax]

,97dd60h

0097498c mov ecx,dword ptr [this]

//靜態繫結

0097498f call base:

:show (

0971555h)

這個要分兩種情況

首先,析構函式是虛函式

class base

virtual ~

base()

private:

int ma;};

intmain()

00904b5f mov edx,dword ptr [ebp-

0e0h]

00904b65 mov eax,dword ptr [edx]

00904b67 mov ecx,dword ptr [ebp-

0e0h]

00904b6d mov edx,dword ptr [eax+4]

//動態繫結

00904b70 call edx

析構函式是普通函式

class base

~base()

private:

int ma;};

intmain()

01092d70 mov dword ptr [this]

,ecx

01092d73 mov ecx,dword ptr [this]

//靜態繫結

01092d76 call base:

:~base (

01091578h)

virtual 虛函式

virtual 虛函式 下面是對c 的虛函式這玩意兒的理解。一,什麼是虛函式 如果不知道虛函式為何物,但有急切的想知道,那你就應該從這裡開始 簡單地說,那些被virtual關鍵字修飾的成員函式,就是虛函式。虛函式的作用,用專業術語來解釋就是實現多型性 polymorphism 多型性是將介面與實現進...

虛函式(virtual)

上面提到動態多型主要通過虛函式機制實現,這裡介紹以下虛函式。和普通的函式宣告方式相同,只要在函式的返回值前加上virtual關鍵字,該函式就為虛函式,即virtual 函式型別 函式名 形式引數 虛函式的作用 允許通過基類的指標或引用來訪問基類和派生類的同名函式。include using name...

關於virtual虛函式

1.如果父類定義的是普通virtual函式,1 父類必須提供乙個實現 2 子類如果不需要實現它,可以不在函式成員中列出來,或者類檔案中列出來,不提供實現也可以 子類如果要實現它,則必須在函式成員中列出來 2.如果父類定義的是純virtual函式 1 如果子類仍是個抽象類,可以不宣告它 2 如果子類不...