1. 程式人生 > >c++之友元函式和友元類

c++之友元函式和友元類

c++友元函式一些見解

1、為什麼要引入友元函式:在實現類之間資料共享時,減少系統開銷,提高效率
具體來說:為了使其他類的成員函式直接訪問該類的私有變數

  即:允許外面的類或函式去訪問類的私有變數和保護變數,從而使兩個類共享同一函式

  優點:能夠提高效率,表達簡單、清晰

  缺點:友元函式破環了封裝機制,儘量不使用成員函式,除非不得已的情況下才使用友元函式。

2、什麼時候使用友元函式:

  1)運算子過載的某些場合需要使用友元。

  2)兩個類要共享資料的時候

3、怎麼使用友元函式:

友元函式的引數:

   因為友元函式沒有this指標,則引數要有三種情況:

   1、  要訪問非static成員時,需要物件做引數;--常用(友元函式常含有引數)

   2、  要訪問static成員或全域性變數時,則不需要物件做引數

   3、  如果做引數的物件是全域性物件,則不需要物件做引數

友元函式的位置:

   因為友元函式是類外的函式,所以它的宣告可以放在類的私有段或公有段且沒有區別。

友元函式的呼叫:

   可以直接呼叫友元函式,不需要通過物件或指標
  • 普通的友元函式
#include<iostream>

using namespace std;

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
public:
	Date(int year, int mouth, int day)
		:_year(year)
		, _mouth(mouth)
		, _day(day)
	{}
private:
	int _year;
	int _mouth;
	int _day;
};


ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << ":" << d._mouth << ":" << d._day << endl;
	return _cout;
}

int main()
{
	Date d(2018, 11, 2);
	cout << d << endl;
	return 0;
}
  • 上面的程式碼我過載了 << 運算子。這裡必須放在類外來定義,如果放在類中來定義的話,我的主函式中 cout<< d<< endl 只能這樣寫了:d<<cout<<endl;
  • 為什麼呢?來看看下面程式碼。
  • 我的定義寫在類中,那麼會出現什麼情況呢?操作符 << 只需要傳兩個引數,那麼在類中這樣定義就會傳了三個引數,不要this 指標哦。有人說,那不傳 ostream& _cout 不就好了,啊哈,行啊,那麼第一個引數就是const Date& d。最後呼叫的就要是 d<<cout;這樣子了。所以友元函式是必須的。
class Date
{
	ostream& operator<<(ostream& _cout, const Date& d)
	{
		_cout << d._year << ":" << d._mouth << ":" << d._day << endl;
		return _cout;
	}
public:
	Date(int year, int mouth, int day)
		:_year(year)
		, _mouth(mouth)
		, _day(day)
	{}
private:
	int _year;
	int _mouth;
	int _day;
};

總結:友元函式可以直接訪問類的私有成員,它是定義在類外部的普通函式,不屬於任何類,但需要在類的內部宣告,宣告時需要加friend關鍵字。

問題1:友元函式能不能用const修飾?

回答:不能,在類中,const 修飾函式是修飾函式的什麼?當然是類函式中的this指標了,那麼友元函式有沒有this指標呢?當然沒有this指標了,所以友元函式不能用const修飾。

友元函式可訪問類的私有成員,是不是類的成員函式?

回答:不是,可以這樣理解,友元函式是類的好朋友,那麼類中的私有成員我允許我的朋友來訪問。

友元函式需要放在類的那裡來宣告呢?public?private?還是?

回答:友元函式可以在類定義的任何地方宣告,不受類訪問限定符限制

函式A是類A的友元函式,那麼函式還能是類B 的友元函式呢?

回答:你肯定不止一個朋友吧。一個函式可以是多個類的友元函式。

除了友元函式,還有友元類。

c++.h

#include<iostream>

using namespace std;

class Date
{
	friend class Time;
public:
	Date(int,int,int);
	void Print();
private:
	int _year;
	int _mouth;
	int _day;
};

class Time
{
	friend class Date;
public:
	Time(int ,int ,int);
	void Print();
private:
	int _hour;
	int _minut;
	int _second;
};

c++.cpp

#include<iostream>
#include"c++.h"
using namespace std;

	Date::Date(int year = 1990, int mouth = 1, int day = 1)
		:_year(year)
		, _mouth(mouth)
		, _day(day)
	{}
	void Date::Print()
	{
		Time t(11,101,10);
		cout << _year << "-" << _mouth << "-" << _day << t._hour << "-" << t._minut << "-" << t._second << endl;
	}


	Time::Time(int hour = 11, int minut = 10, int second = 10)
		:_hour(hour)
		, _minut(minut)
		, _second(second)
	{}
	void Time::Print()
	{
		Date d(100, 101, 102);
		cout << d._year << "-" << d._mouth << "-" << d._day << _hour << "-" << _minut << "-" << _second << endl;
	}


void Func()
{
	Date d(100,101,102);
	d.Print();
	Time t(10,11,12);
	t.Print();
	
}

int main()
{
	Func();
	return 0;
}
  • 這個要看清楚友元函式必須要在標頭檔案中宣告,在另一個檔案中來定義。為什麼?你自己放在一個檔案中你就知道了,我說不清楚。
  • 上面的例子是個友元類,友元類的所有成員函式都可以是另一個類的友元函式,都可以訪問另一個類中的非公有成員。

注意:

  • 友元的優缺點
  • 優點:提高了程式執行效率
  • 缺點:破壞了類的封裝性和隱藏性
  • 友元關係是單向的,不具有交換性。
  • 比如上述Time類和Date類,在Time類中宣告Date類為其友元類,那麼可以在Date類中直接訪問Time 類的私有成員變數,但想在Time類中訪問Date類中私有的成員變數則不行。
  • 友元關係不能傳遞 如果B是A的友元,C是B的友元,則不能說明C時A的友元。