選自 博客園 一點心青
私有成員變量的概念,在腦海中的現象是,以private關鍵字聲明,是類的實現部分,不對外公開,不能在對象外部訪問對象的私有成員變量.
然而,在實現拷貝構造函數和賦值符函數時,在函數里利用對象直接訪問了私有成員變量,因而,產生了困惑.下面以具體實例進行說明:
疑惑:為什么第26行和第32行代碼可以編譯通過,而第39行和第40行代碼會產生編譯錯誤?
1 class CTest { 2 public: 3 CTest(int i); 4 CTest(const CTest& rhs); 5 CTest& operator=(const CTest& rhs); 6 void printCTest(const CTest& rhs); 7 private: 8 int value; 9 }; 10 11 CTest::CTest(int i):value(i) 12 { 13 cout<<"Contructor of CTest"<<endl; 14 } 15 16 CTest::CTest(const CTest& rhs):value(rhs.value) 17 { 18 cout<<"Copy contructor of CTest"<<endl; 19 } 20 21 CTest& CTest::operator=(const CTest& rhs) 22 { 23 cout<<"Assign function of CTest"<<endl; 24 if(this == &rhs) 25 return *this; 26 value = rhs.value; //通過對象訪問私有成員變量 27 return *this; 28 } 29 30 void CTest::printCTest(const CTest& rhs) 31 { 32 cout<<rhs.value<<endl; //通過對象訪問私有成員變量 33 } 34 35 int main() 36 { 37 CTest t = 1; 38 CTest tt = 2; 39 // cout<<t.value<<endl; //通過對象訪問私有成員變量,編譯錯誤 40 // cout<<tt.value<<endl; //通過對象訪問私有成員變量,編譯錯誤 41 t.printCTest(tt); 42 }
產生這種疑惑的原因是自己對私有成員變量的理解有誤,封裝是編譯期的概念,是針對類型而非對象的,在類的成員函數中可以訪問同類型實例對象的私有成員變量.
具體的解析如下:從變量value的符號是怎么解析的分析.
1.確定符號的查找域
如第26行代碼,當編譯器發現value變量時,它會在value變量所屬的對象rhs的類域中尋找該符號.
2.確定當前域中哪些符號可以訪問
由第1步可知,當前查找的域是類域,而printCTest函數在CTest類體中,所以printCTest可以訪問CTest類中的所有變量(包括私有成員變量),因而value符號在CTest類域中被找到.
如第39行代碼,main函數不在CTest類體中,所以main函數不可以訪問CTest類域中的私有成員變量.
3.符號已查找到,編譯通過
類成員變量的訪問權限是編譯器強加的,編譯器可以找到value,通過編譯,自然就可以訪問到value變量的值.
直覺上,我們會以為第26行代碼中value符號的查找域應該是對象rhs對應的作用域,然而C++編譯器的實現卻是在對象rhs的類域查找value符號.
啟發:有些直覺是靠不住的,需要深入分析其背后的實現原理,才可以理解透徹.