今天在看TAF源碼的時候,發現下面一段有趣的代碼:
getSmallerProxyPrx = Application::getCommunicator()->stringToProxy(MobileAssist.JiangeSmallerServer.GetSmaller); //此處T為GetSmallerPrx template T stringToProxy(const string& objectName,const string& setName="") { T prx = NULL; stringToProxy(objectName, prx,setName); return prx; } //此處T為GetSmallerPrx template void stringToProxy(const string& objectName, T& proxy,const string& setName="") { //getServantProxy中new ServantProxy()並返回 ServantProxy * pServantProxy = getServantProxy(objectName,setName); //將ServantProxy類型的指針強制轉換為GetSmallerProxy類型的指針 //並放入GetSmallerProxy類型的智能指針中 proxy = (typename T::element_type*)(pServantProxy); } 我們看一看這行代碼: proxy = (typename T::element_type*)(pServantProxy); 此處的proxy 的類型是T,具體來說就是GetSmallerPrx (更具體的說,是taf::TC_AutoPtr < MobileAssist::GetSmallerProxy >)。 而pServantProxy的類型是ServantProxy *。 (typename T::element_type*)(pServantProxy)
將ServantProxy 類型的指針強制轉換成GetSmallerProxy類型的指針,而ServantProxy是GetSmallerProxy的基類——我的第一反應是——這是非常危險的!比如如果GetSmallerProxy訪問了某個ServantProxy沒有的成員變量,將造成越界訪問。
不過事實上,上面的假設並不成立——GetSmallerProxy沒有新的成員變量。
但是有新的成員函數——而事實是,子類特有的成員函數是可以正常訪問的:
這是不是說明,類的成員函數並不占用類對象的內存空間(如果占用的話,此處的訪問將越界)。
所以我做了一個簡單的實驗:
#include using namespace std; class A { public: A(){} ~A(){} }; class B { public: B(){} virtual ~B(){} }; class C { public: C() {} ~C() {} int add(int a, int b) { return a+b; } }; int main() { cout << "Size(A) = " << sizeof(A) << endl; cout << "Size(B) = " << sizeof(B) << endl; cout << "Size(C) = " << sizeof(C) << endl; return 0; } ./testClassFun Size(A) = 1 Size(B) = 8 Size(C) = 1
結論:成員函數是不占用類對象內存空間的。
一般情況下,同一個類的不同對象,共享成員函數的代碼。成員函數的代碼存儲在對象空間之外。換句話說,成員函數的代碼,都不占據對象的存儲空間。所以類的成員函數,對於類來講,一方面是邏輯上的“屬於”,一方面是物理上的“不依賴”。
所以如果成員函數未使用任何成員變量的話,不管是不是static的,都能正常工作。在調用成員函數時,將this指針傳給函數以指明以哪個類對象調用。
因此,前面的類型向下轉換是沒問題的,並不會造成越界訪問~