當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 關(guān)于C++中的友元
1. 起源:
類(lèi)實(shí)現(xiàn)了數(shù)據(jù)的隱藏與封裝,類(lèi)的數(shù)據(jù)成員一般定義為私有成員,僅能通過(guò)類(lèi)的成員函數(shù)才能讀寫(xiě)。如果數(shù)據(jù)成員定義為公共的,則又破壞了封裝性。但是某些情況下,需要頻繁讀寫(xiě)類(lèi)的數(shù)據(jù)成員,特別是在對(duì)某些成員函數(shù)多次調(diào)用時(shí),由于參數(shù)傳遞、類(lèi)型檢查和安全性檢查等都需要時(shí)間開(kāi)銷(xiāo),而影響程序的運(yùn)行效率。
2. 概念:
友元是一種定義在類(lèi)外部的普通函數(shù),但他需要在類(lèi)體內(nèi)進(jìn)行說(shuō)明,為了和該類(lèi)的成員函數(shù)加以區(qū)別,在說(shuō)明時(shí)前面加以關(guān)鍵字friend。友元不是成員函數(shù),但是他能夠訪問(wèn)類(lèi)中的私有成員。友元的作用在于提高程序的運(yùn)行效率,但是,他破壞了類(lèi)的封裝性和隱藏性,使得非成員函數(shù)能夠訪問(wèn)類(lèi)的私有成員。導(dǎo)致程序維護(hù)性變差,因此使用友元要慎用。
友元較為實(shí)際的應(yīng)用是在運(yùn)算符重載,這種應(yīng)用可以提高軟件系統(tǒng)的靈活性
3. 分類(lèi):友元函數(shù)、友元成員、友元類(lèi)
4. 友元函數(shù):
1)概念:是一種說(shuō)明在類(lèi)定義體內(nèi)的非成員函數(shù)
2)格式:friend 返回值類(lèi)型 函數(shù)名(參數(shù)表){ 函數(shù)體 }
3)說(shuō)明:
A. 友元函數(shù)是在類(lèi)中說(shuō)明的一個(gè)函數(shù),它不是該類(lèi)的成員函數(shù),但可以訪問(wèn)該類(lèi)的所有成員,它是獨(dú)立于任何類(lèi)的一般的外界函數(shù)。
B. 由于不是類(lèi)的成員,所以沒(méi)有this指針,訪問(wèn)該類(lèi)的對(duì)象的成員時(shí)必須使用對(duì)象名,而不能直接使用類(lèi)的成員名。
C. 雖然友元函數(shù)是在類(lèi)中說(shuō)明的,但其名字的作用域在類(lèi)外,作用域的開(kāi)始點(diǎn)在說(shuō)明點(diǎn),結(jié)束點(diǎn)和類(lèi)名相同
【案例1】
#include <iostream>
#include <string.h>
//普通函數(shù)可以訪問(wèn)類(lèi)中的私有成員
using namespace std;
class Grade
{
public:
Grade(int ch, int ma):chinese(ch), math(ma){}
friend void show(Grade &gr);//友元函數(shù)的說(shuō)明
private:
int chinese;
int math;
};
void show(Grade &gr)//友元函數(shù)的實(shí)現(xiàn)
{
cout << "chinese: " << gr.chinese << endl;//沒(méi)有this,只能用對(duì)象調(diào)用
cout << "math: " << gr.math << endl;
}
int main()
{
Grade gr(89, 90);
show(gr);//友元函數(shù)的調(diào)用
return 0;
}
5. 友元類(lèi):
1)概念:某個(gè)類(lèi)可以是另一個(gè)類(lèi)的友元,這樣作為友元的類(lèi)中的所有成員函數(shù)都可以訪問(wèn)另一個(gè)類(lèi)中的私有成員。
2)格式:friend class 類(lèi)名;
【案例2】
#include <iostream>
#include <string.h>
//其他類(lèi)的所有成員函數(shù)都可以訪問(wèn)此類(lèi)的私有成員:Boy類(lèi)中的成員函數(shù)disp可以訪問(wèn)Girl類(lèi)中的成員
using namespace std;
class Boy;//在類(lèi)Name中需要使用類(lèi)Grade,so先聲明
class Girl
{
public:
Girl(char *n)
{
strcpy(name, n);
}
private:
char name[32];
friend class Boy;//類(lèi)Grade是類(lèi)Name的友元,so在類(lèi)grade中可以使用類(lèi)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)特點(diǎn):
A. 友元關(guān)系不能被繼承。
B. 友元關(guān)系是單向的,不具有交換性。若類(lèi)B是類(lèi)A的友元,類(lèi)A不一定是類(lèi)B的友元,要看在類(lèi)中是否有相應(yīng)的聲明。
C. 友元關(guān)系不具有傳遞性。若類(lèi)B是類(lèi)A的友元,類(lèi)C是B的友元,類(lèi)C不一定是類(lèi)A的友元,同樣要看類(lèi)中是否有相應(yīng)的申明
6. 友元成員函數(shù):
1)概念:另一個(gè)類(lèi)的成員函數(shù)可以作為某個(gè)類(lèi)的友元,只是在聲明友元函數(shù)時(shí)要加上成員函數(shù)所在的類(lèi)名。
2)格式:friend 類(lèi)名 :: 成員函數(shù)名;
【案例3】
#include <iostream>
#include <string.h>
//其他類(lèi)的一個(gè)成員函數(shù)都可以訪問(wèn)此類(lèi)的私有成員:Boy類(lèi)中的成員函數(shù)disp可以訪問(wèn)Girl類(lèi)中的成員
using namespace std;
class Girl;//在類(lèi)Name中需要使用類(lèi)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類(lèi)中的成員函數(shù)為友元函數(shù)
//可以訪問(wèn)Girl類(lèi)中的成員
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;
}