“類名稱”+“::”調用方式
注:
對靜態函數或靜態成員的調用方式不做分析;
以下提到的測試環境為vc6.0;
調試程序時看到這樣的代碼:
pObj->ClassName::Function();
開始不理解為什麼要在“->”後加上類名“ClassName::”,一般使用中類名稱加“::”(ClassName::)是用來調用靜態函數或靜態成員的,帶著疑問做了下嘗試。
定義類A:
class A
{
public:
void Test()
{
int nVal= 8;
int nVal1 = nVal;
}
};
調用方式:
A* pA = NULL;
pA->A::Test();
測試能夠順利通過。但是調試時進入A類的Test()函數發現this指針為空:
修改類A為:
class A
{
public:
A(){ m_nVal = 5; }
~A(){}
void Test()
{
int nVal= 8;
int nVal1 = nVal;
int nVal2 = m_nVal; //調用成員變量
}
protected:
int m_nVal; //增加成員變量
};
再次執行:
A* pA = NULL;
pA->A::Test();
這次程序會崩潰,調試發現是在使用成員變量時崩潰,如下圖:
通過上面的測試初步得出結論,當采用pA->A::Test()這種方式進行調用時,如果Test()函數中沒有使用類的非靜態成員變量,調用的指針(具體的類對象指針this)是否為空可以不考慮,能夠順利通過,如果Test()函數中使用了類的非靜態成員變量,則必須要求調用的指針不為null,也就是必須有已分配了內存空間的類對象,因為這些非靜態成員變量的空間是分配在類對象上的。對於類的靜態成員這裡就不在敘述(因為類的靜態成員屬於類本身,不屬於類對象)。
到這裡問題就來了,調用時直接寫成pA->Test()不就可以了,干嘛寫的這麼別扭,給人感覺很深奧的樣子(事實是有點深奧),通過經驗猜測應該和繼承有關系,於是做了如下嘗試:
修改類A:
class A
{
public:
A(){ m_nVal = 5; }
~A(){}
virtual void Test() //變為虛函數
{
int nVal= 8;
int nVal1 = nVal;
int nVal2 = m_nVal;
}
protected:
int m_nVal;
};
增加類B繼承於類A:
class B: public A
{
virtual void Test()
{
int nB = m_nVal;
}
};
調用方式:
A* pA = new B;
pA->Test(); //第一步
pA->A::Test(); //第二步
調試時發現,當執行第一步時進入的是類B(子類)中定義的Test()函數,執行第二步時進入的是類A(父類)中的Test()函數,第一步調用是實現多態的一種方式很常見,而第二種調用方式是刻意破壞多態的結構,已達到指定的去執行父類的函數,我個人不贊成這種寫法,首先它打破了常規寫法,並且看起來不易理解,也不利於維護擴展,完全可以采取其他常見方式實現相應功能。
由於能力有限,如有錯誤和不當之處,敬請廣大讀者批評指正。