一篇文章詳細(xì)解釋C++的友元(friend)
一.友元函數(shù)
友元函數(shù)可以是普通函數(shù)或者類成員函數(shù)。
先看普通函數(shù)聲明為友元函數(shù):
如下所示:
#include <iostream>
#include <cmath>
using namespace std;
class Point
{
//普通函數(shù)聲明為類的友元函數(shù)
friend double TwoPointsDistant(const Point& pnt1, const Point& pnt2);
public:
Point(double x=0, double y=0)
:_x(x), _y(y)
{}
double getPointXAxis() const { return this->_x; }
double getPointYAxis() const { return this->_y; }
private:
double _x;
double _y;
};
//計(jì)算兩點(diǎn)的距離
double TwoPointsDistant(const Point& pnt1, const Point& pnt2)
{
return sqrt( pow((pnt1._x - pnt2._x), 2) + pow((pnt1._y - pnt2._y), 2) );
}
int main()
{
Point point1(1.1,2.2);
Point point2(3.3, 4.4);
cout << TwoPointsDistant(point1, point2) << endl;
system("pause");
return 0;
}
這里說明一點(diǎn):TwoPointsDistant()函數(shù)必須在Point類的定義下面,至于原因,很簡單,你若放在Point上面,Point的數(shù)據(jù)成員_x和_y都沒定義呢,你用個錘子。
再看類成員函數(shù)聲明為友元函數(shù):
還以上面的類為例,現(xiàn)在加一個_PointMove_類,它有一個成員函數(shù)_PointAxisAddOne,_作用是將點(diǎn)的坐標(biāo)都加1。如下:
class PointMove
{
public:
void PointAxisAddOne(Point& pnt);
};
這里就出現(xiàn)了一個問題:_Point_和_PointMove_哪個放在前面?先給出答案,應(yīng)該把_PointMove_放在前面,并且是必須的,如下:
class Point;//前向聲明Point
class PointMove
{
public:
void PointAxisAddOne(Point& pnt);
};
class Point
{
//普通函數(shù)聲明為類的友元函數(shù)
friend double TwoPointsDistant(const Point& pnt1, const Point& pnt2);
//類成員函數(shù)聲明為友元
friend void PointMove::PointAxisAddOne(Point& pnt);
/*這里同前*/
};
//類成員函數(shù)的定義
void PointMove::PointAxisAddOne(Point& pnt)
{
pnt._x = pnt._x + 1;
pnt._y = pnt._y + 1;
}
這里注意,對于類的成員函數(shù),聲明為其他類的友元函數(shù)時需要加上類的作用域,即指出該函數(shù)屬于哪個類。如上面的_PointMove::_。?
同時,需要說明的是,PointAxisAddOne()函數(shù)的定義是必須放在Point類定義后面的,這和普通函數(shù)的道理是一樣的。
最后說明
1.一個函數(shù)Func被聲明為類A的友元函數(shù),那么是不能直接使用this指針來訪問類A的數(shù)據(jù)成員的(當(dāng)然,若Func是類B的成員函數(shù),它可以通過this訪問類B的數(shù)據(jù)成員),這和成員函數(shù)不同。
2.一個函數(shù)Func為什么要聲明為某個類A的友元,就是因?yàn)?code>函數(shù)的參數(shù)類型為類A類型,我想訪問這個類對象的數(shù)據(jù)成員,所以被聲明為類A的友元函數(shù)的參數(shù)類型必定為類A,如friend Func(A& obj);
二.友元類
若是將一個類C都聲明為另一個類A的友元類,則類C中的成員函數(shù)均可訪問類A中的私有數(shù)據(jù)成員。如下:
class Point
{
//友元類
friend class PointInfo;
...
}
class PointInfo
{
public:
//打印點(diǎn)所處象限
void PrintQuadrant(const Point& pnt) const
{
if (pnt._x > 0 && pnt._y > 0)
cout << "點(diǎn)"<<"(" << pnt._x << "," << pnt._y<<")" <<"處于第一象限" << endl;
}
};
當(dāng)然,你也可以把_PointInfo_寫在_Point_前,只是函數(shù)_PrintQuadrant()_的定義就不能在類內(nèi)實(shí)現(xiàn)了,只能在_Point_后實(shí)現(xiàn),原因和前面一樣,不再贅述。
三.完整示例:
#include <iostream>
#include <cmath>
using namespace std;
class Point;
class PointMove
{
public:
void PointAxisAddOne(Point& pnt);
};
class PointInfo
{
public:
//打印點(diǎn)所處象限
void PrintQuadrant(const Point& pnt) const;
};
class Point
{
friend class PointInfo;
friend double TwoPointsDistant(const Point& pnt1, const Point& pnt2);
friend void PointMove::PointAxisAddOne(Point& pnt);
public:
Point(double x=0, double y=0)
:_x(x), _y(y)
{}
double getPointXAxis() const { return this->_x; }
double getPointYAxis() const { return this->_y; }
void PrintAxis(const Point& pnt) const
{
}
private:
double _x;
double _y;
};
//打印點(diǎn)所處象限
void PointInfo::PrintQuadrant(const Point& pnt) const
{
if (pnt._x > 0 && pnt._y > 0)
cout << "點(diǎn)"<<"(" << pnt._x << "," << pnt._y<<")" <<"處于第一象限" << endl;
}
void PointMove::PointAxisAddOne(Point& pnt)
{
pnt._x = pnt._x + 1;
pnt._y = pnt._y + 1;
}
double TwoPointsDistant(const Point& pnt1, const Point& pnt2)
{
return sqrt( pow((pnt1._x - pnt2._x), 2) + pow((pnt1._y - pnt2._y), 2) );
}
int main()
{
Point point1(1.1,2.2);
Point point2(3.3, 4.4);
cout << TwoPointsDistant(point1, point2) << endl;
PointInfo pf;
pf.PrintQuadrant(point1);
system("pause");
return 0;
}
VS2015打印結(jié)果:

四.同一個類(class)的類對象(object)互為友元
還以上面給出的例子為基礎(chǔ),現(xiàn)在在_Point_類加一個成員函數(shù)func(const Point& pnt),它返回點(diǎn)的x軸和y軸的和。如下所示。
class Point
{
/*這里同上*/
double func(const Point& pnt)
{
return pnt._x + pnt._y;
}
private:
double _x;
double _y;
};
現(xiàn)在我生成兩個對象,并作如下操作:
Point point1(1.1,2.2); Point point2(3.3, 4.4); cout << point1.func(point2) << endl;
最后的結(jié)果是打印出7.7??吹竭@里不知道你有沒有疑問:為什么可以通過point1直接訪問point2的私有數(shù)據(jù)成員,而沒有將func()聲明為友元函數(shù)?侯捷老師是這么解釋的:相同class的各個objects之間互為友元。
所以對于一個類A,若有一個成員函數(shù)Fun(A& arg),可以通過arg直接訪問A的私有數(shù)據(jù)成員。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C語言設(shè)計(jì)圖書登記系統(tǒng)與停車場管理系統(tǒng)的實(shí)例分享
這篇文章主要介紹了C語言設(shè)計(jì)圖書登記系統(tǒng)與停車場管理系統(tǒng)的實(shí)例分享,重在以最簡單的一些需求來展示管理系統(tǒng)的設(shè)計(jì)思路,需要的朋友可以參考下2016-06-06
簡單談?wù)勱P(guān)于C++中大隨機(jī)數(shù)的問題
這篇文章主要介紹了關(guān)于C++中大隨機(jī)數(shù)的問題,文中給出了詳細(xì)的示例代碼,相信對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,有需要的朋友可以一起來學(xué)習(xí)學(xué)習(xí)。2017-01-01
C語言數(shù)據(jù)結(jié)構(gòu)進(jìn)階之棧和隊(duì)列的實(shí)現(xiàn)
棧和隊(duì)列,嚴(yán)格意義上來說,也屬于線性表,因?yàn)樗鼈円捕加糜诖鎯壿嬯P(guān)系為 "一對一" 的數(shù)據(jù),但由于它們比較特殊,因此將其單獨(dú)作為一章,做重點(diǎn)講解2021-11-11
C++?qsort函數(shù)排序與冒泡模擬實(shí)現(xiàn)流程詳解
qsort是一個庫函數(shù),基于快速排序算法實(shí)現(xiàn)的一個排序的函數(shù),下面這篇文章主要給大家介紹了關(guān)于C語言qsort()函數(shù)使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
C++對Json數(shù)據(jù)的友好處理實(shí)現(xiàn)過程
在Ajax的應(yīng)用中,前臺基本上會用到JSON作為數(shù)據(jù)交換格式,所以下面這篇文章主要給大家介紹了關(guān)于C++對Json數(shù)據(jù)的友好處理,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
C++ 實(shí)現(xiàn)LRU 與 LFU 的緩存算法
設(shè)計(jì)和實(shí)現(xiàn)一個LRU 緩存機(jī)制。其支持獲取數(shù)據(jù) get 和 寫入數(shù)據(jù) put,設(shè)計(jì)并實(shí)現(xiàn)最少訪問頻率(LFU)緩存的數(shù)據(jù)結(jié)構(gòu)。LFU的每個數(shù)據(jù)塊都有一個引用計(jì)數(shù),所有數(shù)據(jù)塊按照引用計(jì)數(shù)排序,具有相同引用計(jì)數(shù)的數(shù)據(jù)塊則按照時間進(jìn)行排序。其支持get 和 put,具體了解請看下文2021-09-09

