在本文中,您將學習在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的聲明之后定義。