今天在看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指針傳給函數以指明以哪個類對象調用。
因此,前面的類型向下轉換是沒問題的,並不會造成越界訪問~