C++ 類的作用域
在類的作用域之外,普通的數(shù)據(jù)和函數(shù)成員只能由對象、引用或者指針使用成員訪問運算符訪問,對于類類型成員,則使用作用域訪問運算符。
作用域和定在類外部的成員
例如我們定義Window_mgr類的clear成員
因為編譯器在參數(shù)列表之前已經(jīng)明確了我們當(dāng)前正位于Window_mgr類的作用域之中,所以不必再專門說明ScreenIndex是Window_mgr類定義的,screens同理。
另一方面,函數(shù)的返回類型通常出現(xiàn)在函數(shù)名之前,因此當(dāng)成員函數(shù)定義在類的外部時,返回類型中使用的名字都位于作用域之外,這是返回類型必須指明他是哪個類的成員
例如:
名字查找與類的作用域
在我們編寫的程序中名字查找的過程比較直截了當(dāng)
1在名字所在的塊中尋找其聲明語句,只考慮在名字使用之前出現(xiàn)的聲明
2如果沒找到繼續(xù)查找外層作用域
3如果最終沒有找到聲明,報錯
對于定義在類中的成員函數(shù)來說,解析其中名字的方式和上面有區(qū)別
1編譯成員聲明
2直到類全部可見后才編譯函數(shù)體
用于類成員聲明的名字查找
這種兩階段的處理方式只適用于成員函數(shù)中使用的名字,聲明中使用的名字包括返回類型或參數(shù)列表中使用的名字,都必須在使用前確??梢?,如果某個成員的聲明使用了類中沒有出現(xiàn)的名字,則編譯器將會在定義該類的作用域中繼續(xù)查找。
當(dāng)編譯器看到balance的聲明時,他將在Account類中查找對Money的聲明,編譯器只考慮Account中使用Money前出現(xiàn)的聲明,因為沒有找到匹配,所以編譯器會接著到Account的外層作用域中查找。這個例子中,編譯器會找到Money的typedef語句,該類型被用作balance函數(shù)的返回類型,以及數(shù)據(jù)成員bal的類型,另一方面因為balance函數(shù)只有在整個類可見后才被處理,所以return返回的是名為bal的成員不是string對象。
類型名要特殊處理
一般來說內(nèi)層作用域可以重定義外層作用域中的名字,即使該名字已經(jīng)在內(nèi)層使用過,然而在類中,如果成員使用了外層作用域的某個名字,而該名字代表一種類型,則類不能再之后重新定義該名字。
即使Account中定義的Money類型和外層一致,上述代碼依舊是錯誤的。
注意:重新定義類型名字是一種錯誤的行為,但是編譯器并不為此負(fù)責(zé),一些編譯器還是可以通過這樣的代碼。
注意:類型名的定義通常出現(xiàn)在類的開始處,這樣就能確保所有使用該類型的成員都出現(xiàn)在定義之后。
成員定義的普通塊作用域的名字查找
解析成員函數(shù)中使用的名字
1在成員函數(shù)內(nèi)查找該名字的聲明,只有在函數(shù)使用之前出現(xiàn)的聲明才被考慮
2如果在成員函數(shù)內(nèi)沒有找到,則在類內(nèi)繼續(xù)查找,這時類的所有成員都可以被考慮。
3如果類內(nèi)沒有找到聲明,在成員函數(shù)定義之前的作用域內(nèi)繼續(xù)查找
一般來說不要使用成員的名字作為某個成員函數(shù)的參數(shù)!
處理cursor時,他首先在函數(shù)作用域內(nèi)查找表達(dá)式中用到的名字,函數(shù)的參數(shù)位于作用域中,因此用到的height使用的是參數(shù)height。
例子中,height參數(shù)隱藏了同名的成員
并不建議使用上述代碼,如果參數(shù)使用其他名字是最好的方法。另一方面即使成員函數(shù)內(nèi)隱藏了成員height但是我們可以強行訪問它。
類作用域之后,在外圍的作用域中查找
如果我們需要外層作用域的height
在文件中名字的出現(xiàn)對其進(jìn)行解析
成員定義在類的外部時,名字查找的第三步不僅要考慮類定義之前的全局作用域中的聲明,還要考慮在成員函數(shù)定義之前的全局作用域中的聲明。
verify的聲明在Screen類的定義之前是不可見的,然而名字查找的第三步包括了成員函數(shù)出現(xiàn)之前的全局作用域,因為verify的聲明位于setHeight的定義之前,所以可以被正常使用。