1. 起源:
類實現了數據的隱藏與封裝,類的數據成員一般定義為私有成員,僅能通過類的成員函數才能讀寫。如果數據成員定義為公共的,則又破壞了封裝性。但是某些情況下,需要頻繁讀寫類的數據成員,特別是在對某些成員函數多次調用時,由于參數傳遞、類型檢查和安全性檢查等都需要時間開銷,而影響程序的運行效率。
2. 概念:
友元是一種定義在類外部的普通函數,但他需要在類體內進行說明,為了和該類的成員函數加以區別,在說明時前面加以關鍵字friend。友元不是成員函數,但是他能夠訪問類中的私有成員。友元的作用在于提高程序的運行效率,但是,他破壞了類的封裝性和隱藏性,使得非成員函數能夠訪問類的私有成員。導致程序維護性變差,因此使用友元要慎用。
友元較為實際的應用是在運算符重載,這種應用可以提高軟件系統的靈活性
3. 分類:友元函數、友元成員、友元類
4. 友元函數:
1)概念:是一種說明在類定義體內的非成員函數
2)格式:friend 返回值類型 函數名(參數表){ 函數體 }
3)說明:
A. 友元函數是在類中說明的一個函數,它不是該類的成員函數,但可以訪問該類的所有成員,它是獨立于任何類的一般的外界函數。
B. 由于不是類的成員,所以沒有this指針,訪問該類的對象的成員時必須使用對象名,而不能直接使用類的成員名。
C. 雖然友元函數是在類中說明的,但其名字的作用域在類外,作用域的開始點在說明點,結束點和類名相同
【案例1】
#include <iostream>
#include <string.h>
//普通函數可以訪問類中的私有成員
using namespace std;
class Grade
{
public:
Grade(int ch, int ma):chinese(ch), math(ma){}
friend void show(Grade &gr);//友元函數的說明
private:
int chinese;
int math;
};
void show(Grade &gr)//友元函數的實現
{
cout << "chinese: " << gr.chinese << endl;//沒有this,只能用對象調用
cout << "math: " << gr.math << endl;
}
int main()
{
Grade gr(89, 90);
show(gr);//友元函數的調用
return 0;
}
5. 友元類:
1)概念:某個類可以是另一個類的友元,這樣作為友元的類中的所有成員函數都可以訪問另一個類中的私有成員。
2)格式:friend class 類名;
【案例2】
#include <iostream>
#include <string.h>
//其他類的所有成員函數都可以訪問此類的私有成員:Boy類中的成員函數disp可以訪問Girl類中的成員
using namespace std;
class Boy;//在類Name中需要使用類Grade,so先聲明
class Girl
{
public:
Girl(char *n)
{
strcpy(name, n);
}
private:
char name[32];
friend class Boy;//類Grade是類Name的友元,so在類grade中可以使用類Name的成員
};
class Boy
{
public:
void disp(Girl &);
};
void Boy :: disp(Girl &g)
{
cout << "name: " << g.name << endl;
}
int main()
{
Boy b;
Girl g("lily");
b.disp(g);
return 0;
}
3)特點:
A. 友元關系不能被繼承。
B. 友元關系是單向的,不具有交換性。若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應的聲明。
C. 友元關系不具有傳遞性。若類B是類A的友元,類C是B的友元,類C不一定是類A的友元,同樣要看類中是否有相應的申明
6. 友元成員函數:
1)概念:另一個類的成員函數可以作為某個類的友元,只是在聲明友元函數時要加上成員函數所在的類名。
2)格式:friend 類名 :: 成員函數名;
【案例3】
#include <iostream>
#include <string.h>
//其他類的一個成員函數都可以訪問此類的私有成員:Boy類中的成員函數disp可以訪問Girl類中的成員
using namespace std;
class Girl;//在類Name中需要使用類Grade,so先聲明
class Boy
{
public:
Boy(int a):age(a){}
void disp(Girl &);
private:
int age;
};
class Girl
{
public:
Girl(char *n)
{
strcpy(name, n);
}
friend void Boy :: disp(Girl &);//聲明Boy類中的成員函數為友元函數
//可以訪問Girl類中的成員
private:
char name[32];
};
void Boy :: disp(Girl &g)
{
cout << "girl's name: " << g.name << endl;
cout << "boy's age: " << age << endl;
}
int main()
{
Boy b(22);
Girl g("lily");
b.disp(g);
return 0;
}