1. 程式人生 > >C++ 關於類與物件在虛擬函式表上唯一性問題 淺析

C++ 關於類與物件在虛擬函式表上唯一性問題 淺析

【摘要】

很多教材上都有介紹到虛指標、虛擬函式與虛擬函式表,有的說類物件共享一個虛擬函式表,有的說,一個類物件擁有一個虛擬函式表;還有的說,無論使用者聲明瞭多少個類物件,但是,這個VTABLE虛擬函式表只有一個;也有的在說,每個具有虛擬函式的類的物件裡面都有一個VPTR虛擬函式指標,這個指標指向VTABLE的首地址,每個類的物件都有這麼一種指標。今天,我們就來解決這個問題,同一個類的不同物件,是不是擁有“相同”的虛擬函式表,這個相同是物理上的相同(記憶體地址)還是邏輯上的相同(資料結構)。本文現詳述如下!

【正文】

虛指標:每個含有虛方法(虛擬函式)物件裡有虛表指標,指向虛表。

虛擬函式表:虛擬函式表是順序存放虛擬函式地址的,虛表是順序表,

表裡存放了虛擬函式的地址。

C++的編譯器應該是保證虛擬函式表的指標存在於物件例項中最前面的位置(這是為了保證取到虛擬函式表的有最高的效能——如果有多層繼承或是多重繼承的情況下)。這意味著我們通過物件例項的地址得到這張虛擬函式表,然後就可以遍歷其中函式指標,並呼叫相應的函式。

【程式碼示例】

#include <iostream>
using namespace std;
 
class Base {
public:
	virtual void f() { cout << "Base::f" << endl; }
	virtual void g() { cout << "Base::g" << endl; }
	virtual void h() { cout << "Base::h" << endl; }
 
};
typedef void(*Fun)(void);

int main()
{
	Fun pFun = NULL;
	Base obj_1,obj_2;
	// obj_1 虛擬函式表 — 第一個函式
	pFun = (Fun)*((int*)*(int*)(&obj_1));
	pFun();
	pFun = (Fun)*(((int*)*(int*)(&obj_1))+1);
	pFun();
	// 輸出 虛擬函式表地址 與 虛擬函式表元素 的值
	cout << "obj_1 虛擬函式表地址:" << (int*)(&obj_1) << endl;
	cout << "obj_2 虛擬函式表地址:" << (int*)(&obj_2) << endl;
	cout << "obj_1 虛擬函式表 — 第一個函式地址:" << (int*)*(int*)(&obj_1) << endl;
	cout << "obj_2 虛擬函式表 — 第一個函式地址:" << (int*)*(int*)(&obj_2) << endl;
	return 0;
}
/*
輸出 :
Base::f      
Base::g 
obj_1 虛擬函式表地址:0018FF40                         
obj_2 虛擬函式表地址:0018FF3C                         
obj_1 虛擬函式表 — 第一個函式地址:0046F0AC           
obj_2 虛擬函式表 — 第一個函式地址:0046F0AC           
Press any key to continue                                                                                 
*/

【結論】

不同物件虛擬函式表表中元素是相等的,邏輯上是一樣的,存放的都是類中虛擬函式的地址;

不同物件虛擬函式表的記憶體地址是不一樣,物理上是不一樣的,一個物件是一個新的表。

【相關推薦】

詳址:http://blog.csdn.net/haoel/article/details/1948051#comments