【C++深度剖析教程6】C++之友元
這幾天在復習數學考試,都沒有學C++,今天抽空來學一點。
什么是友元?
- 友元是C++中的一種關系
 - 友元發生在函數與類之間或者類與類之間
 - 友元關系是單向的,不能傳遞
 
在具體講解友元的性質之前,我們先來看看一個程序,這個程序是計算兩點之間的距離:
#include <stdio.h> #include <math.h>class Point { private:double x;double y; public:Point(double x,double y){this->x = x; //this指針指向當前的對象this->y = y;}double getX(){return x;}double getY(){return y;} };double func(Point& p1,Point& p2) {double ret = 0;ret = (p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +(p1.getY() - p2.getY()) * (p1.getY() - p2.getY());ret = sqrt(ret);return ret; }int main() {Point p1(1,2);Point p2(10,20);printf("p1(%f,%f)\n",p1.getX(),p1.getY());printf("p2(%f,%f)\n",p2.getX(),p2.getY());printf("|p1-p2| = %f\n",func(p1,p2));return 0; }上面代碼運行結果為:
p1(1.000000,2.000000) p2(10.000000,20.000000) |p1-p2| = 20.124612看著也沒什么大問題。下面我們來簡單分析一下這個程序的實用性:進行計算這個兩點之間的距離時的代碼為:
ret = (p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +(p1.getY() - p2.getY()) * (p1.getY() - p2.getY());進行了8次函數的調用!!!這么簡單的計算,就需要調用8次函數,這效率之慢在當初C++誕生的時候,是不被大多數人接受的,大多數人用C編程習慣了,都是可以直接這樣調用的:
ret = (p1.x - p2.x) * (p1.x - p2.x) +(p1.y - p2.y) * (p1.y - p2.y);然而C++里面你就不能像上面那樣直接調用類(C里面可以是結構體或者數組)的成員變量。因為它是private類型的變量。那么在C++誕生的那個年代,人們為了讓C++語言完全兼容C語言,就在C++中加入了友元的存在。那么友元的定義以及性質是什么樣的呢?
- 在類中以friend關鍵字聲明友元
 - 類的友元可以是其他類或者具體的函數
 - 友元不是類的一部分
 - 友元不受類中訪問級別的限制
 - 友元可以直接訪問具體類的所有成員
 
直接將上面的代碼修改一下看看:
#include <stdio.h> #include <math.h>class Point { private:double x;double y; public:Point(double x,double y){this->x = x; //this指針指向當前的對象this->y = y;}double getX(){return x;}double getY(){return y;}friend double func(Point& p1,Point& p2); };double func(Point& p1,Point& p2) {double ret = 0;ret = (p1.x - p2.x) * (p1.x - p2.x) +(p1.y - p2.y) * (p1.y - p2.y);ret = sqrt(ret);return ret; }int main() {Point p1(1,2);Point p2(10,20);printf("p1(%f,%f)\n",p1.getX(),p1.getY());printf("p2(%f,%f)\n",p2.getX(),p2.getY());printf("|p1-p2| = %f\n",func(p1,p2));return 0; }運行結果為:
p1(1.000000,2.000000) p2(10.000000,20.000000) |p1-p2| = 20.124612這樣看來,我們已經實現了直接訪問類的私有成員變量。上面的代碼,func函數是Point類的友元,可以直接訪問Point的所有數據。但是這樣做,又不好,為什么呢?
 友元的尷尬:
- 友元是為了兼顧C語言的高效性而誕生的
 - 友元直接破壞了面向對象的封裝性
 - 友元在實際產品中的高效是得不償失的
 - 友元在現代軟件工程中已經被逐漸遺棄
 
雖然基于以上的尷尬讓友元這個功能在現代軟件工程中很少被使用,但是我們學習嘛,肯定是都要學的,哈哈~
友元需要注意的一些事項:
- 友元關系不具備傳遞性
 - 類的友元可以是其他類的成員函數
 - 類的友元可以是某個完整的類(所有的成員函數都是友元)
下面我們再分析一個代碼,來看看友元的真實面目: 
運行結果為:
b.n = B c.n = C分析代碼知:類B是C的友元,類A是B的友元,所以在B中可以直接訪問C的私有成員變量,在A中可以直接訪問B的成員變量。 那么在A中能否直接訪問C呢?試驗一下將上面的代碼注釋掉得部分恢復,編譯運行,運行結果為:
test.cpp: In member function ‘void ClassA::getClassCName(ClassC&)’: test.cpp:6: error: ‘const char* ClassC::n’ is private test.cpp:44: error: within this context很顯然,A是不能訪問C的私有成員的。
總結一下:
- 友元是為了兼顧C語言的高效而誕生的
 - 友元直接破壞了面向對象的封裝性
 - 友元關系不具備傳遞性
 - 類的友元可以是其他類的成員函數
 - 類的友元可以是某個完整的類
 
想獲得各種學習資源以及交流學習的加我(有我博客中寫的代碼的原稿):
 qq:1126137994
 微信:liu1126137994
 可以共同交流關于嵌入式,操作系統,C++語言,C語言,數據結構等技術問題。
總結
以上是生活随笔為你收集整理的【C++深度剖析教程6】C++之友元的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 软考论文写作的时间分配
 - 下一篇: C++给函数传数组参数C++给函数传数组