1.友元
- 如果你想直接看輸出運算符重載,可以直接跳過前面這一部分
1.1什麼是友元
- 友元就是聲明一個函數或者類 F , 該類 F 可以随意通路你自己類中的任何成員.
- 友元是單向的, 比如有 A 和 B ,将 B 作為 A 的友元類. 注意,這裡的 A 是主體, B 是 A 的一個友元. 這個時候, B可以随意通路 A , 而 A 并不能随意通路 B
- 友元是不具備傳遞性的. 比如(依舊使用上面的 A 和 B ):B 是 A 的友元,我們再加入一個 C , C 是 B 的友元,那 C 就可以随意看 B 的内容,但是此時的 C 并不能随意的看 A 的内容(雖然 B 可以随意看 A 的内容)
1.2友元函數
- 友元函數是将一個類的外部函數(外部函數表示不是該類裡面聲明的函數),通過在類的内部添加一個
修飾的函數聲明,就可以讓該函數成為該類的成員函數,外部函數就可以直接通路類對象的私有變量friend
void fun(test a)//外部對函數進行實作,通路是需要傳入友元類的對象
{
cout << "val is" << a.val <<endl; // 可以直接通路test類對象中私有成員變量
}
class test
{
friend void fun();//一般隻在類中添加友元函數的聲明,而不做實作
private: //這裡是私有的
int val;
}
1.3友元類
- 友元類和友元方法一緻,隻不過這裡操作的對象有一個函數變為一個類了,依舊是使用
修飾,下面是一個例子friend
class B
{
void fun(A a)//需要通過友元類的對象進行通路
{
cout << "val is" << a.val << endl;
}
};
class A
{
friend class B;
private:
int val;
};
=============================================================================
2.operator<<
- 在讨論之前,我們先要知道,在C++中的運算符,可以算作是一個函數名,這個函數有多重的重載方法,有豐富的使用方式。
- 1.首先,我們在使用
輸出的時候,到底發生了什麼。cout <<
- 在一開始,
方法調用了一個方法,叫做cout
。該方法接收的 第一個參數 是輸出流對象operator<<
,第二個參數 才是我們想要輸出的對象。我們通過該輸出流對象,想标準輸出所需要輸出的内容。ostream
-
在傳參的時候,就會預設傳遞自身,也就是cout
。注意,強調一下,這裡是第一個參數,一定要牢記,這是第一個參數。誰調用operator所對應的運算符,誰就有權力傳遞第一個參數。ostream
- 重頭戲來了,我們為了使用
運算符重載将我們的自定義對象按照合理的格式輸出,我們勢必需要傳遞一個<<
指針,這個是跑不了的,但是通過 對象 調用this
運算符重載的時候,<<
指針又會去搶占第一個參數的位置,此時的調用方法是這樣的(通過對象調用):this
。這裡寫的是沒有問題的,如果你不将A << cout
設定為友元,就需要這樣調用,也隻能這樣調用。因為誰在<<
之前,調用<<
,誰就具有傳遞第一個參數的權利。<<
- 為了證明我說的是對的,我寫了一個例子,證明可以像
這種形式進行輸出,你大可将該代碼放入你的編譯器試試~~A << cout
- 在一開始,
#include<iostream>
using namespace std;
class data
{
public:
void operator<<(ostream&out)
{
cout << "hello operator <<" << endl;
}
};
int main()
{
data A;
A << cout;//這不就是上面的輸出方式嘛,最終會正常顯示,毫無問題,
//除了使用起來不太美觀~~ 像極了 輸入cin的使用,hhh
//這裡的實際展開的是 void operator<<(*this,ostream&cout)
//看到了嗎, this已經偷偷的被加到了第一個參數的位置
return 0;
}
- 2.我們該如何做
- 為了避免兩者互相搶占第一個參數位置的情況,并且滿足我們日常使用習慣,我們可以将該
運算符重載為全局函數,這樣,對象調用全局函數的時候,就不會傳遞<<
指針了(this
指針隻會在調用自己類的成員函數的時候才會傳遞)。this
- 但是這個時候,雖然可以正常傳參了,對象會被當做第二個參數傳遞進去,但是如果我們需要輸出類對象的私有成員變量時,又不能正常輸出,因為非類的内部成員不能通路啊~~。
- 這個時候,我們加入友元,
,将該全局方法聲明為類的友元方法,這樣,就可以對類的私有成員進行随意的通路了。friend
- 我們的目的達到了~~,我們可以按照正常的操作邏輯來調用
運算符了<<
- 下面的代碼才是咋們想要的代碼,你可以拷貝到你的編譯器裡試試看,多看幾次,多想想兩個參數的位置,就能想清楚了
- 為了避免兩者互相搶占第一個參數位置的情況,并且滿足我們日常使用習慣,我們可以将該
如果您覺得有幫助到您的話,不妨給我點個贊 😃,謝謝,雖然點贊沒啥用,但能夠讓我感受到幫助到您而感到十分開心 😃,如果您有問題,可以評論告訴我~~
#include<iostream>
using namespace std;
class data
{
public:
data() : key(10)
{}
private:
friend void operator<<(ostream&out, data& tmp);
int key;
};
void operator<<(ostream&out, data& tmp)
{
cout << "hello operator <<" << endl;
cout << tmp.key << endl;
}
int main()
{
data A;
cout << A;
system("pause");
return 0;
}