天天看點

友元,以及為什麼operator<<需要被聲明為友元1.友元2.operator<<

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

      在傳參的時候,就會預設傳遞自身,也就是

      ostream

      。注意,強調一下,這裡是第一個參數,一定要牢記,這是第一個參數。誰調用operator所對應的運算符,誰就有權力傳遞第一個參數。
    • 重頭戲來了,我們為了使用

      <<

      運算符重載将我們的自定義對象按照合理的格式輸出,我們勢必需要傳遞一個

      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;
}
           

繼續閱讀