關於虛函式表的個人總結
1.虛函式表的建立:
乙個類存在虛函式的時候,編譯器會為這個類建立乙個虛函式表,這個表由這個類的所有物件共同所有。
在建立這個類的類物件的時候將這個物件的前4個位元組作為這項這個虛函式表的指標。即類物件的首位址中的內容存放的是虛函式表的位址。
虛函式表的首位址裡面存放的是第乙個虛函式的首位址,如果有多個虛函式,則第二個虛函式的位址即為第乙個虛函式首位址加上偏移量,
位址如果用int*為單位表示的話偏移量加1,對於以16進製制位表示的話則加4,(見下例,如果看著暈的話,不用看具體的,下面會有更加詳細的解釋).
----(int*)*(int*)*(int*)(&b)是第乙個函式的位址,則第二個函式的位址是(int*)*((int*)*(int*)(&b)+1)或者(int*)*(int*)(*(int*)(&b)+4)----
?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include
using
namespace
std;
class
base
virtual
void
g()
virtual
void
h()
};
int
main()
執行結果如下:
2.關於(int*)*(int*)*(int*)(&b)的解釋
(int*)*(int*)*(int*)(&b)(1)(&b)表示對物件取位址,返回的實際上是乙個base*型別的指標,也就是乙個位址。(2)(int*)(&b)強制將(base*)型別轉換成(int*)型指標,注意這裡(int*)做的轉換是從(base*)到(int*)實際上cout比如下面的幾條語句:?注釋的地方是錯誤的關鍵就在於0x567890是乙個十六進製制數與位址無關,用(int*)可以將16進製制數轉化成位址,然後用指標p指向位址。1
2
3
int
* p;
//p=0x567890;
p=(
int
*)0x567890;
(5)*(int*)*(int*)(&b),表示取虛函式表中第乙個位址中的內容,即虛函式表中存放的第乙個函式的位址的十六進製制數表示,是int型
(6)(int*)*(int*)*(int*)(&b),將表示第乙個函式位址的16進製制數轉換成位址,即第乙個函式的位址
(7)如果以位址為單位求下乙個函式的位址則在位址後加4,如
(int*)*(int*)(*(int*)(&b)+4)
如果以int*為單位的話求系乙個函式位址則直接加1,如
(int*)*((int*)*(int*)(&b)+1)
3.如何通過虛函式表進行函式呼叫。
現在在原來的**中定義乙個函式指標。?
1
typedef
void
(*fun)(
void
);
//如果不用fun宣告p函式指標的話可以直接寫麻煩的式子:void(*p)(void)=(fun)(int*)*((int*)*(int*)(&b)+1);
在main函式中
呼叫函式f:?
1
2
3
fun p=null;
p=(fun)(
int
*)*(
int
*)*(
int
*)(&b);
p();
呼叫函式g?
1
2
p=(fun)(
int
*)*((
int
*)*(
int
*)(&b)+1);
//或者p=(fun)(int*)*(int*)(*(int*)(&b)+4);
p();
呼叫函式h ?
1
2
p=(fun)(
int
*)*((
int
*)*(
int
*)(&b)+2);
//或者p=(fun)(int*)*(int*)(*(int*)(&b)+8);
p();
結果:
關於虛函式表的個人總結
原文 關於虛函式表的個人總結 1.虛函式表的建立 乙個類存在虛函式的時候,編譯器會為這個類建立乙個虛函式表,這個表由這個類的所有物件共同所有。在建立這個類的類物件的時候將這個物件的前4個位元組作為這項這個虛函式表的指標。即類物件的首位址中的內容存放的是虛函式表的位址。虛函式表的首位址裡面存放的是第乙...
關於虛函式表的心得
如果父類中存在虛函式,那麼父類,以及由其直接和間接派生的子類都會存在虛函式表。每個類的虛函式表中儲存的是這個類繼承的虛函式以及自己實現的虛函式的位址。比如說,base 類 中定義了虛函式 virtual f 而由base類派生的derived 類 過載了這個虛函式 virtual f 那麼,base...
虛函式表指標,虛函式表
對c 了解的人都應該知道虛函式 virtual function 是通過一張虛函式表 virtual table 來實現的。簡稱為v table。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了繼承 覆蓋的問題,保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了 這個例項...