虛函式表分析

2021-10-05 07:18:57 字數 3805 閱讀 9572

// project100.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。

//#include

"pch.h"

#include

using

namespace std;

//父類

class

base

virtual

voidg(

)virtual

voidh(

)};class

derive

:public base

/* void f()

void g()

void h() */};

intmain()

//typedef void(*func)(void); //定義乙個函式指標型別

//func f = (func)vptr[0]; //f就是函式指標變數。 vptr[0]是指向第乙個虛函式的。

//func g = (func)vptr[1];

//func h = (func)vptr[2];

///*func i = (func)vptr[3];

//func j = (func)vptr[4];*/

//f();

//g();

//h();

i();

//base *dpar = new base();

//long *pvptrpar = (long *)dpar;

//long *vptrpar = (long *)(*pvptrpar);

//for (int i = 0; i <= 4; i++) //迴圈5次;

////func fpar = (func)vptrpar[0];

//func gpar = (func)vptrpar[1];

//func hpar = (func)vptrpar[2];

//cout << "--------------------" << endl;

//fpar();

//gpar();

//hpar();

//(1)乙個類只有包含虛函式才會存在虛函式表,同屬於乙個類的物件共享虛函式表,但是有各自的vptr(虛函式表指標),

//當然所指向的位址(虛函式表首位址)相同。

//(2)父類中有虛函式就等於子類中有虛函式。話句話來說,父類中有虛函式表,則子類中肯定有虛函式表。因為你是繼承父類的。

//也有人認為,如果子類中把父類的虛函式的virtual去掉,是不是這些函式就不再是虛函式了?

//只要在父類中是虛函式,那麼子類中即便不寫virtual,也依舊是虛函式。

//但不管是父類還是子類,都只會有乙個虛函式表,不能認為子類中有乙個虛函式表+父類中有乙個虛函式表,

//得到乙個結論:子類中有兩個虛函式表。

//子類中是否可能會有多個虛函式表呢?後續我們講解這個事;

//(3)如果子類中完全沒有新的虛函式,則我們可以認為子類的虛函式表和父類的虛函式表內容相同。

//但,僅僅是內容相同,這兩個虛函式表在記憶體中處於不同位置,換句話來說,這是內容相同的兩張表。

//虛函式表中每一項,儲存著乙個虛函式的首位址,但如果子類的虛函式表某項和父類的虛函式表某項代表同乙個函式

//(這表示子類沒有覆蓋父類的虛函式),

//則該表項所執行的該函式的位址應該相同。

//(4)超出虛函式表部分內容不可知;

typedef

void

(*func)

(void);

//定義乙個函式指標型別

derive derive;

long

*pvptrderive =

(long*)

(&derive)

;//0x00b09b6c

long

*vptrderive =

(long*)

(*pvptrderive)

; func f1 =

(func)vptrderive[0]

;//0x00b0119f

func f2 =

(func)vptrderive[1]

;//0x00b0150f

func f3 =

(func)vptrderive[2]

;//0x00b01325

func f4 =

(func)vptrderive[3]

;//0x69726544

func f5 =

(func)vptrderive[4]

;//0x3a3a6576

derive derive2 = derive;

//呼叫拷貝建構函式

long

*pvptrderive2 =

(long*)

(&derive2)

;long

*vptrderive2 =

(long*)

(*pvptrderive2)

; base base = derive;

//直接用子類物件給父類物件值,子類中的屬於父類那部分內容會被編譯器自動區分

//(切割)出來並拷貝給了父類物件。

//所以base base = derive;實際幹了兩個事情:

//第乙個事情:生成乙個base物件

//第二個事情:用derive來初始化base物件的值。

//這裡編譯器給咱們做了乙個選擇,顯然derive初始化base物件的時候,

//derive的虛函式表指標值並沒有覆蓋base物件的虛函式表指標值,

//編譯器幫我們做到了這點;

long

*pvptrbase =

(long*)

(&base)

;//0x00b09b34

long

*vptrbase =

(long*)

(*pvptrbase)

; func fb1 =

(func)vptrbase[0]

;//0x00b0119f

func fb2 =

(func)vptrbase[1]

;//0x00b01177

func fb3 =

(func)vptrbase[2]

;//0x00b01325

func fb4 =

(func)vptrbase[3]

;//0x00000000

func fb5 =

(func)vptrbase[4]

;//0x65736142

//oo(物件導向) 和ob(基於物件)概念:

//c++通過類的指標和引用來支援多型,這是一種程式設計風格,這就是我們常說的物件導向。object-oriented model;

//ob(object-based),也叫adt抽象資料模型【abstract datatype model】,不支援多型,執行速度更快,因為

//因為 函式呼叫的解析不需要執行時決定(沒有多型),而是在編譯期間就解析完成,記憶體空間緊湊程度上更緊湊,

//因為沒有虛函式指標和虛函式表這些概念了;

//base *pbase = new derive();

//base &base2 = derive2;

//但顯然,ob的設計靈活性就差;

//c++既支援物件導向程式設計(繼承,多型)(oo),也支援基於物件(ob)程式設計。

虛函式表指標,虛函式表

對c 了解的人都應該知道虛函式 virtual function 是通過一張虛函式表 virtual table 來實現的。簡稱為v table。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了繼承 覆蓋的問題,保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了 這個例項...

多重繼承虛函式表分析

project100.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include pch.h include using namespace std 基類1 class base1 virtual voidg 基類2 class base2 virtual voidi 子類 cl...

C 虛函式表例項分析

多型是c 物件導向程式設計的乙個重要特性。以前看到虛函式覺得很神奇,為什麼就能實現多型了呢。最初的時候曾設想,要實現執行時多型,應該讓物件的某個部分始終指向乙個固定的位址,子類繼承的時候,就修改這個位址的內容。這樣,父類和子類都是到同乙個固定位址去讀取內容,在執行時就能表現不同行為。在看了 深度探索...