1. 程式人生 > >對c++友元函式和友元類的理解

對c++友元函式和友元類的理解

1,友元函式的定義和作用

我們已知道類具有封裝和資訊隱藏的特性。只有類的成員函式才能訪問類的私有成員,程式中的其他函式是無法訪問私有成員的。非成員函式可以訪問類中的公有成員,但是如果將資料成員都定義為公有的,這又破壞了隱藏的特性。另外,應該看到在某些情況下,特別是在對某些成員函式多次呼叫時,由於引數傳遞,型別檢查和安全性檢查等都需要時間開銷,而影響程式的執行效率。

為了解決上述問題,提出一種使用友元的方案。友元是一種定義在類外部的普通函式,但它需要在類體內進行說明,為了與該類的成員函式加以區別,在說明時前面加以關鍵字friend。友元不是成員函式,但是它可以訪問類中的私有成員。友元的作用在於提高程式的執行效率(即減少了型別檢查和安全性檢查等都需要的時間開銷),但是,它破壞了類的封裝性和隱藏性,使得非成員函式可以訪問類的私有成員。

2,上述的訪問不是直接訪問,對於普通私有成員變數是通過物件訪問,對於私有靜態變數是通過類訪問。

為什麼不能直接訪問呢?

先了解一下為什麼成員函式可以直接訪問成員變數?

成員函式能夠訪問類的成員變數是因為傳遞了指向當前物件的this指標,它如果訪問資料成員對其操作是this指向的物件的資料成員,是有實際意義的 。

友元函式不是成員函式,沒有傳遞隱藏的this指標,只能間接訪問。

這點其實和靜態成員函式一樣,靜態成員函式也是沒有this指標的,所以它只能訪問靜態成員變數或者通過物件訪問非靜態成員變數。

例子:

class Rect  
{  
public:  
	Rect()      // 建構函式,計數器加1  
	{  
		count++;  
	}  
	//Rect(const Rect& r)
	//{
	//	width = r.width;
	//	height = r.height;
	//	count++;
	//}
	~Rect()     // 解構函式,計數器減1  
	{  
		count--;  
	}  
	static int getCount()       // 返回計數器的值  
	{  
		return count;  
	} 
	friend int get();
private:  
	int width;  
	int height;  
	static int count;       // 一靜態成員做為計數器  
};  

int Rect::count = 0;        // 初始化計數器  
int get()
{
	return Rect::count;//友元函式通過類訪問私有靜態成員變數
}
int main()  
{  
	Rect rect1;  
	cout<<"The count of Rect: "<<Rect::getCount()<<endl;//通過類訪問公有靜態成員函式,輸出1  

	Rect rect2(rect1);   // 使用rect1複製rect2,此時應該有兩個物件  
	cout<<"The count of Rect: "<<Rect::getCount()<<endl; //輸出1
	cout << get() << endl;//輸出1
	//cout << Rect::count << endl;//不能編譯通過,不能訪問私有成員
	system("pause");
	return 0;  
}  
3,類和類之間的友元關係不能繼承。

下邊轉載自:

http://blog.csdn.net/shandianling/article/details/7469361

C++ Primer中有如下描述:友元關係不能繼承。基類的友元對派生類的成員沒有特殊訪問
許可權。如果基類被授予友元關係,則只有基類具有特殊訪問許可權,該基類的派生類不能訪問授予友元關係的類。

 然而通過實踐發現,VS編譯器並沒有安裝上述描述來處理,下面的規則與上述描述相悖,卻符合VS編譯器的處理規則。

注:有待通過g++編譯器來驗證。

1 友元類的繼承問題

1.1 A類的友元B的派生類C 不能訪問A類的private或protect成員變數。但可以通過B提供的介面來訪問A。(廢話肯定可以)

  1. #include <iostream> 
  2. usingnamespace   std;   
  3. class B;   
  4. class A   
  5. {   
  6.     int a;   
  7. public:   
  8.     A(int x=0) { a=x; }   
  9.     friendclass B;   
  10. };   
  11. class B   
  12. {   
  13.     int b;   
  14. public:   
  15.     void fun(A& ob){ cout << ob.a << endl;}   
  16. };   
  17. class C:public B  
  18. {   
  19. public:   
  20.     //void fun2(A& ob){ cout <<ob.a <<endl;}   //派生類新加的函式卻不能訪問A,此句會報錯
  21. };   
  22. void   main()   
  23. {   
  24.     A a(55);   
  25.     C c;   
  26.     c.fun(a); //C是B的派生類   通過基類B的函式fun仍然可以訪問 
  27. }   


1.2.  Base的友元可以通過Base的派生類Drived訪問Base的private,protect成員變數,但不能訪問Drived的private,protect成員變數。(這一點似乎與《C++ primer》裡說的有點衝突)

個人理解:Drived的物件本身就包含Base,Base的友元Frnd自然就可以訪問Base的部分。

  1. #include <iostream> 
  2. usingnamespace std;   
  3. class Base   
  4. {   
  5.     int m_a;   
  6. public:   
  7.     Base(int x=0){ m_a=x; }   
  8.     friendclass Frnd;   
  9. };   
  10. class Drived:public Base   
  11. {   
  12. private:  
  13.     int m_c;  
  14. public:   
  15.     Drived(int x):Base(x){m_c=x;}   
  16. };  
  17. class Frnd   
  18. {  
  19. public:   
  20.     void fun(Base& ob) { cout <<ob.m_a << endl; }   
  21.     void fun2(Drived& ob)   
  22.     {  
  23.         cout << ob.m_a<<endl;  
  24.         //cout <<ob.m_c<<endl; //編譯錯誤
  25.     }   
  26. };   
  27. int main()   
  28. {   
  29.     Drived d(1);   
  30.     Frnd f;   
  31.     f.fun(d);   
  32.     f.fun2(d);  
  33.     system("pause");  
  34.     return 0;  
  35. }   

3 友元類的傳遞問題

A的友元是B,B的友元是C,那A的友元是C? 不是,友元類不具有傳遞性。


相關推薦

c++函式理解

1,友元函式的定義和作用 我們已知道類具有封裝和資訊隱藏的特性。只有類的成員函式才能訪問類的私有成員,程式中的其他函式是無法訪問私有成員的。非成員函式可以訪問類中的公有成員,但是如果將資料成員都定義為公有的,這又破壞了隱藏的特性。另外,應該看到在某些情況下,特別是在對某

c++之函式

c++友元函式一些見解 1、為什麼要引入友元函式:在實現類之間資料共享時,減少系統開銷,提高效率 具體來說:為了使其他類的成員函式直接訪問該類的私有變數 即:允許外面的類或函式去訪問類的私有變數和保護變數,從而使兩個類共享同一函式 優點:能夠提高效率,表達簡單、清晰

C++函式用法詳解

在C++中,我們使用類對資料進行了隱藏和封裝,類的資料成員一般都定義為私有成員,成員函式一般都定義為公有的,以此提供類與外界的通訊介面。但是,有時需要定義一些函式,這些函式不是類的一部分,但又需要頻繁地訪問類的資料成員,這時可以將這些函式定義為該函式的友元函式。除了友元函式

C++函式C++ friend)詳解

私有成員只能在類的成員函式內部訪問,如果想在別處訪問物件的私有成員,只能通過類提供的介面(成員函式)間接地進行。這固然能夠帶來資料

C++過載(2):通過成員函式函式過載

分別通過成員函式和友元函式完成過載 #include <iostream> using namespace std; class Complex { public: Complex(double real =0,double imag=0):real(real),imag(i

(函式成員函式) C++

        有些情況下,允許特定的非成員函式訪問一個類的私有成員,同時仍阻止一般的訪問,這是很方便做到的。例如被過載的操作符,如輸入或輸出操作符,經常需要訪問類的私有資料成員。         友元(frend)機制允許一個類將對其非公有成員的訪問權授予指定的函式或者類

C++實現輸入輸出運算子過載、函式成員函式實現複數Complex

今天答應幫朋友做一個C++題目,頗費了一番周折,終於還是寫出來了,讓很久沒敲程式碼的我反省了一下,也回憶了以前學過的知識。 題目要求如下: 一、按下列要求編制複數類,並除錯通過: 1)  基本的建構函式; 2)  成員運算子+、-實現複數的加減運算; 3)  友元運算子+

採用成員函式函式計算給定兩個座標點之間的距離

設計一個用來表示直角座標系的Location類,在主程式中建立類Location的兩個物件A和B,要求A的座標點在第3象限,B的座標點在第2象限,分別採用成員函式和友元函式計算給定兩個座標點之間的距離,要求按如下格式輸出結果: A(x1,y1), B(x2,y2), Distance1=d1

c++成員運算子過載運算子過載的比較(以++,--運算子為例)

1、對雙目運算子而言,成員運算子過載函式引數列表中含有一個引數,而友元運算子過載函式引數列表含有兩個引數;對單目運算子而言,成員運算子過載函式引數列表中沒有引數,而友元運算子過載函式引數列表含有一個引數。 2、雙目運算子一班可以被過載為友元運算子和成員函式運算

成員函式函式完成二元運算子過載

傳智掃地僧課程學習筆記。 運算子過載實現方法, 1,用成員函式 2,用友元函式 區別是,傳參是否內部使用this指標, 全域性函式、類成員函式方法實現運算子過載步驟          1)要承認操作符過載是一個函式,寫出函式名稱operator+ ()       

成員函式函式 完成二元一元運算子過載(進階1)

二元運算子過載: 全域性函式: #include <iostream> using namespace std; class Complex{//複數類 private: int

C++學習筆記(10)運算子過載,函式

c++允許我們為運算子定義專門的函式,這被稱為運算子過載: 運算子可以簡化字串的操作,‘+’,以及使用關係運算符比較字串,[ ]運算子訪問向量中的元素; 例如: #include <iostream> #include <string> #include <

成員函式函式實現一元運算子過載

使用友元函式實現一元運算子的過載 實現一元運算子的前置過載 即前置++a; #include <iostream> using namespace std; class Comple

C++模板函式)宣告的三種情況

根據《C++ Primer》第三版16.4節的敘述,C++類模板友元分為以下幾種情況1.非模板友元類或友元函式。 書上給了一個例子:class Foo{    void bar();};template <class T>class QueueItem{   

運算子過載函式作為成員函式函式

作為類成員函式的例子: #include <iostream> using namespace std; class Complex{ public: Complex(){real = 0; imag = 0;} Complex(double r

“friend宣告函式函式卻依舊無法訪問該類的私有屬性”的解決方法

“friend宣告友元函式,友元函式卻依舊無法訪問該類的私有屬性”的解決 一次C++作業題, 搞了很久弄明白了, 雖然成功了, 但VS2015依舊有紅線提示錯誤, 不過不影響編譯、執行, 這似乎是VS

函式的宣告與使用

1.友元函式的簡單介紹 1.1為什麼要使用友元函式 在實現類之間資料共享時,減少系統開銷,提高效率。如果類A中的函式要訪問類B中的成員(例如:智慧指標類的實現),那麼類A中該函式要是類B的友元函式。具體來說:為了 使其他類的成員函式直接訪問該類的私有變數。即:允許外

c語言時間的處理函式計時的實現

關鍵字:c語言 時間函式 time.h c語言時間函式,時間頭函式 所有程式碼編譯環境:MSVC6.0 1,時間的獲取: 通過time()函式來獲得日曆時間(Calendar Time),其原型為:time_t time(time_t * timer); #incl

C++中純虛擬函式多型的理解

    抽象類是一種特殊的類,它是為了抽象和設計的目的為建立的,它處於繼承層次結構的較上層。       ⑴抽象類的定義:       稱帶有純虛擬函式的類為抽象類。       ⑵抽象類的作用:       抽象類的主要作用是將有關的操作作為結果介面組織在

C++ string成員函式cstring庫函式

首先是C字串: C 庫函式 - strcmp()   比較2個C字串的字典序大小 描述 C 庫函式 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字