在本文中,您將學習在C ++中創(chuàng)建友元函數和友元類,并在程序中有效地使用它們。
OOP的重要概念之一是數據隱藏,即非成員函數無法訪問對象的私有或受保護的數據。
但是,有時這種限制可能迫使程序員編寫冗長而復雜的代碼。因此,C ++編程內置了一種機制,可以從非成員函數訪問私有或受保護的數據。
這是使用友元函數和友元類完成的。
如果將函數定義為友元函數,則可以使用函數訪問類的私有數據和受保護數據。
通過使用關鍵字friend,編譯器知道給定的函數是友元函數。
要訪問數據,應該在類的內部以關鍵字friend開始聲明友元函數(可以是類內部的任何地方,可以是private部分,也可以是public部分)。
class class_name { ... .. ... friend return_type function_name(argument/s); ... .. ... }
現在,您可以將友元函數定義為訪問該類數據的普通函數。friend定義中未使用任何關鍵字。
class className { ... .. ... friend return_type functionName(argument/s); ... .. ... } return_type functionName(argument/s) { ... .. ... // 可以從這個位置訪問className的私有和受保護數據 //因為此函數是className的友元函數。 ... .. ... }
/* C ++程序演示友元函數的工作。*/ #include <iostream> using namespace std; class Distance { private: int meter; public: Distance(): meter(0) { } //友元函數 friend int addFive(Distance); }; // 友元函數的定義 int addFive(Distance d) { //從非成員函數訪問私有數據 d.meter += 5; return d.meter; } int main() { Distance D; cout<<"距離: "<< addFive(D); return 0; }
輸出結果
距離: 5
這里,友元函數addFive()在Distance類中聲明。因此,可以從這個函數訪問私有數據。
盡管此示例為您提供了有關友元函數概念的想法,但并未顯示任何有意義的用途。
當您需要對兩個不同類的對象進行操作時,將有一種更有意義的用法。那時,友元函數會非常有幫助。
你完全可以在不使用friend函數的情況下操作兩個不同類的對象,但是這個程序會很長,很復雜,很難理解。
#include <iostream> using namespace std; // 前置聲明 class B; class A { private: int numA; public: A(): numA(12) { } //友元函數聲明 friend int add(A, B); }; class B { private: int numB; public: B(): numB(1) { } // 友元函數聲明 friend int add(A , B); }; //函數add()是類A和B的友元函數 //訪問成員變量numA和numB int add(A objectA, B objectB) { return (objectA.numA + objectB.numB); } int main() { A objectA; B objectB; cout<<"Sum: "<< add(objectA, objectB); return 0; }
輸出結果
Sum: 13
在這個程序中,類A和B已經將add()聲明為friend函數。因此,這個函數可以訪問這兩個類的私有數據。
在這里,add()函數將兩個對象objectS和object的私有數據numA和numB相加,并將其返回給main函數。
為了使這個程序正常工作,應該像上面的實例中所示的那樣,對一個類B進行前置聲明。
這是因為使用以下代碼在class A中引用了class B的友元函數:friend int add(A,B);
類似地,像一個友元函數一樣,一個類也可以使用關鍵字friend成為另一個類的友元類。例如:
... .. ... class B; class A { // class B 是 class A的友元類 friend class B; ... .. ... } class B { ... .. ... }
當一個類成為另一個類的friend類(友元類)時,這就意味著這個類的所有成員函數都是另一個類的友元函數。
在這個程序中,B類的所有成員函數都是A類的朋友函數,因此B類的任何成員函數都可以訪問A類的私有和受保護的數據,但是A類的成員函數不能訪問B類的數據。
如何實現classA與B互為友元,即A可以訪問B的私有,B也可以訪問A的私有呢?案例如下:
#include <iostream> using namespace std; //必須提前聲明class B不然編譯會報錯 class B; class A{ private: int a; public: friend class B; A(){ cout << "類A被構造" << endl; a = 20; } ~A(){ cout << "類A被析構" << endl; } void show(B & b); }; class B{ private: int b; public: friend class A; B(){ cout << "類B的構造" << endl; b = 12; } ~B(){ cout << "類B被析構" << endl; } void show(A &a){ cout << "a="<<a.a ; cout << " b=" <<b<<endl; } }; //函數不能放在class A 中,不然會編譯報錯 void A::show(B &b){ cout << "a="<<a ; cout << " b="<<b.b<< endl; } int main(){ A a; B b; a.show(b); b.show(a); return 0; }運行結果:
類A被構造 類B的構造 a=20 b=12 a=20 b=12 類B被析構 類A被析構
互為友元類的做法就是,在class A中聲明friend class B;在classB 中聲明friend class A;
注意:類A中使用到了類B的地方必須在類B的聲明后定義,在類A中只能聲明。例如左邊類A中的show函數,不能在類A中直接定義,只能放在類B的聲明之后定義。