友元分為兩部分內容
- 友元函數
- 友元類
友元函數
問題:當我們嘗試去重載operator<<
,然后發現沒辦法將operator<<
重載成成員函數。因為cout
的輸出流對象和隱含的this
指針在搶占第一個參數的位置。this
指針默認是第一個參數也就是左操作
數了。但是實際使用中cout
需要是第一個形參對象,才能正常使用。所以要將operator<<
重載成全局函數。但又會導致類外沒辦法訪問成員,此時就需要友元來解決。operator>>
同理。
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常規調用
// 因為成員函數第一個參數一定是隱藏的this,所以d1必須放在<<的左側
ostream& operator<<(ostream& _cout)
{
_cout << _year << "-" << _month << "-" << _day << endl;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
友元函數可以直接訪問類的私有成員,它是定義在類外部的普通函數,不屬于任何類,但需要在類的內部聲明,聲明時需要加friend
關鍵字。
class Date
{
//友元聲明 這個聲明你放在公有還是私有都是不影響的,它只是一個聲明
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
_cin >> d._year;
_cin >> d._month;
_cin >> d._day;
return _cin;
}
int main()
{
Date d;
cin >> d;
cout << d << endl;
return 0;
}
特征:
- 友元聲明放在
public
還是private
,還是兩個都不放 都是不影響的 - 友元函數不是類的成員函數
- 友元函數不能用const修飾,(提一嘴:靜態成員也不能用const修飾,因為沒有this 指針)
- 一個函數可以是多個類的友元函數
- 友元函數的調用與普通函數的調用原理相同
友元類
友元類的所有成員函數都可以是另一個類的友元函數,都可以訪問另一個類中的非公有成員。
- 友元關系是單向的,不具有交換性。
比如下面描述Time類和Date類,在Time類中聲明Date類為其友元類,那么可以在Date類中直接訪問Time類的私有成員變量,但想在Time類中訪問Date類中私有的成員變量則不行。 - 友元關系不能傳遞
- 如果C是B的友元, B是A的友元,則不能說明C時A的友元。
友元關系不能繼承,在繼承位置再給大家詳細介紹。
class Time
{
friend class Date; // 聲明日期類為時間類的友元類,則在日期類中就直接訪問Time類
中的私有成員變量
public:
Time(int hour = 0, int minute = 0, int second = 0)
: _hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接訪問時間類私有的成員變量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
內部類
概念:如果一個類定義在另一個類的內部,這個內部類就叫做內部類。內部類是一個獨立的類,它不屬于外部類,更不能通過外部類的對象去訪問內部類的成員。外部類對內部類沒有任何優越的訪問權限
特性:
- 內部類可以定義在外部類的
public
、protected
、private
都是可以的。 - 注意內部類可以直接訪問外部類中的
static
成員,不需要外部類的對象/類名。 - sizeof(外部類)=外部類,和內部類沒有任何關系
思考下面代碼的結果:
#include<iostream>
using namespace std;class A
{
public://內部類class B{public:private:int _b;};private:int _a;};int main()
{cout << sizeof(A) << endl;return 0;
}
這個就可以說明:sizeof(外部類) = 外部類
與內部類沒有任何關系
還需要理解的就是:
B類
和 A類
,雖然B類
在A類
的內部,但實際上B類
和A類
是兩個獨立的類,只是說,B類 要受到 A 類的 域
和 訪問限定符
的限制
所以可以這么說,A 對象里面 是 沒有B對象的
如果內部類 是定義在public
中的 就可以通過 域作用限定符來進行訪問
如果內部類 是定義在private
中的 無法通過 域作用限定符來進行訪問
注意:內部類就是外部類的友元類,參見友元類的定義,內部類可以通過外部類的對象參數來訪問外部類中的所有成員。但是外部類不是內部類的友元