C++友元函數(shù)和友元類的使用詳解
1、友元函數(shù)是什么?
首先,得有個比較總體的認(rèn)識,我個人認(rèn)為友元函數(shù)是一個補(bǔ)丁。
在 C++ 中,一個類中可以有 public、protected、private 三種屬性的成員,通過對象可以訪問 public 成員,只有本類中的函數(shù)可以訪問本類的 private 成員。
但是c++中依舊保留了,獨(dú)立的函數(shù),也就是不依賴某個class存在(你可以理解為c中的函數(shù)),如果此時我們函數(shù)需要調(diào)用某一個class中定義的變量,這時就無法實(shí)現(xiàn)這個功能。所以友元函數(shù)或友元類就出現(xiàn)了,專門來打這個補(bǔ)丁。
小結(jié):友元函數(shù)即針對訪問某一個class中的成員變量和成員函數(shù)。
2、友元函數(shù)的關(guān)鍵字friend
其中友元函數(shù)按照定義或聲明的位置來區(qū)分,可以分為兩種:
(1):class外定義的函數(shù)
(2):其他類中定義的成員函數(shù)
2.1、class外定義的函數(shù)在某個class中說明為這個類的友元函數(shù)
標(biāo)題看起來有點(diǎn)拗口,但是卻很好的解釋了,這個友元函數(shù)定義和聲明的狀態(tài)?
閑話少說,直接看代碼
#include <iostream>
using namespace std;
class Student{
public:
Student(char *name, int age, float score); //構(gòu)造函數(shù)
public:
friend void show(Student *pstu); //將show()聲明為類Student的友元函數(shù)
private:
char *m_name;
int m_age;
float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
//非成員函數(shù)
void show(Student *pstu){
cout<<pstu->m_name<<"的年齡是 "<<pstu->m_age<<",成績是 "<<pstu->m_score<<endl;
}
int main(){
Student stu("小明", 15, 90.6);
show(&stu); //調(diào)用友元函數(shù)
Student *pstu = new Student("李磊", 16, 80.5);
show(pstu); //調(diào)用友元函數(shù)
return 0;
}友元函數(shù)的聲明:
shennd void show(Student *pstu); //將show()聲明為類Student的友元函數(shù)
友元函數(shù)的定義:
void show(Student *pstu){
cout<<pstu->m_name<<"的年齡是 "<<pstu->m_age<<",成績是 "<<pstu->m_score<<endl;
}注意看,我標(biāo)紅的地方,即友元函數(shù)的形參,是class類型的指針。具體函數(shù)的代碼中,使用指針和->來調(diào)用類中的成員函數(shù)或成員變量。
除了上面說的,還有幾點(diǎn)需要額外說明
*1)、友元函數(shù),可以聲明在任何位置,public,private,protect,而且都不會影響
*2)、如果函數(shù)不聲明為友元函數(shù),但是形參是class類型的指針,則也可以訪問其public成員或函數(shù)。
友元函數(shù)的調(diào)用:
- 我們在主函數(shù)中調(diào)用,注意此時的形參,先聲明一個實(shí)例,然后取這個實(shí)1例的地址作為實(shí)參,這是因?yàn)槌蓡T函數(shù)在調(diào)用時會隱式地增加 this 指針,指向調(diào)用它的對象,從而使用該對象的成員;
- 而 show() 是非成員函數(shù),沒有 this 指針,編譯器不知道使用哪個對象的成員,要想明確這一點(diǎn),就必須通過參數(shù)傳遞對象(可以直接傳遞對象,也可以傳遞對象指針或?qū)ο笠茫?,并在訪問成員時指明對象。
2.2、將其他類的成員函數(shù)聲明為友元函數(shù)
friend 函數(shù)不僅可以是全局函數(shù)(非成員函數(shù)),還可以是另外一個類的成員函數(shù)。請看下面的例子:
#include <iostream>
using namespace std;
class Address; //提前聲明Address類
//聲明Student類
class Student{
public:
Student(char *name, int age, float score);
public:
void show(Address *addr);
private:
char *m_name;
int m_age;
float m_score;
};
//聲明Address類
class Address{
private:
char *m_province; //省份
char *m_city; //城市
char *m_district; //區(qū)(市區(qū))
public:
Address(char *province, char *city, char *district);
//將Student類中的成員函數(shù)show()聲明為友元函數(shù)
friend void Student::show(Address *addr);
};
//實(shí)現(xiàn)Student類
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
cout<<m_name<<"的年齡是 "<<m_age<<",成績是 "<<m_score<<endl;
cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"區(qū)"<<endl;
}
//實(shí)現(xiàn)Address類
Address::Address(char *province, char *city, char *district){
m_province = province;
m_city = city;
m_district = district;
}
int main(){
Student stu("小明", 16, 95.5f);
Address addr("陜西", "西安", "雁塔");
stu.show(&addr);
Student *pstu = new Student("李磊", 16, 80.5);
Address *paddr = new Address("河北", "衡水", "桃城");
pstu -> show(paddr);
return 0;
}friend void Student::show(Address *addr);
這是在Address中聲明Student中的show()函數(shù)為,Address的友元函數(shù)
3、友元類
不僅可以將一個函數(shù)聲明為一個類的“朋友”,還可以將整個類聲明為另一個類的“朋友”,這就是友元類。
友元類中的所有成員函數(shù)都是另外一個類的友元函數(shù)。
class Address{
public:
Address(char *province, char *city, char *district);
public:
//將Student類聲明為Address類的友元類
friend class Student;
private:
char *m_province; //省份
char *m_city; //城市
char *m_district; //區(qū)(市區(qū))
};注意第6行中,定義一個友元類,結(jié)構(gòu)上簡單的多,就是在此class中,+一個聲明語句即可“friend class Student;”
關(guān)于友元,有兩點(diǎn)需要說明:
- 友元的關(guān)系是單向的而不是雙向的。如果聲明了類 B 是類 A 的友元類,不等于類 A 是類 B 的友元類,類 A 中的成員函數(shù)不能訪問類 B 中的 private 成員。
- 友元的關(guān)系不能傳遞。如果類 B 是類 A 的友元類,類 C 是類 B 的友元類,不等于類 C 是類 A 的友元類。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++學(xué)習(xí)之cstdbool和cstddef頭文件封裝源碼分析
這篇文章主要為大家介紹了C++學(xué)習(xí)之cstdbool和cstddef頭文件封裝源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
C語言關(guān)于include順序不同導(dǎo)致編譯結(jié)果不同的問題
這篇文章主要介紹了在日常調(diào)試C語言中include的順序不同從而影響最后編譯結(jié)果不同的問題,究其原因是寫代碼的習(xí)慣所導(dǎo)致,下面跟小編一起來看看吧2022-04-04
C和C++如何實(shí)現(xiàn)互相調(diào)用詳解
在學(xué)習(xí)c++中用到一些古老的c語言庫時,在工作中我們經(jīng)常要使用C和C++混合編程,下面這篇文章主要給大家介紹了關(guān)于C和C++如何實(shí)現(xiàn)互相調(diào)用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01
C/C++中的?Qt?StandardItemModel?數(shù)據(jù)模型應(yīng)用解析
QStandardItemModel?是標(biāo)準(zhǔn)的以項(xiàng)數(shù)據(jù)為單位的基于M/V模型的一種標(biāo)準(zhǔn)數(shù)據(jù)管理方式,本文給大家介紹C/C++中的?Qt?StandardItemModel?數(shù)據(jù)模型應(yīng)用解析,感興趣的朋友跟隨小編一起看看吧2021-12-12

