C++中的友元函數主要應用於以下場景:
友元函數
第一種場景
代碼中有一個全局函數,該函數想要去訪問某個類的成員變量(該類的成員變量是private的,且該類並未提供任何獲取獲取私有成員變量的public方法),這時候可以在這個類中把該全局函數聲明為友元函數,這樣這個全局函數就具備了能夠獲取那個類的私有成員變量的資格。
例:通過友元函數獲取Person類的各項字段信息:
main.cpp
#include <iostream>
#include "Person.h"
void showPersonInfo(Person *person) { std::cout << person->m_name << ", age is: " << person->m_age << ", sex is: " << person->m_sex << std::endl; } int main() { Person *person = new Person("xp.chen", 20, 1); showPersonInfo(person); delete person; getchar(); return 0; }
person.h
#pragma once class Person { private: char *m_name; int m_age; int m_sex; public: Person(char *name, int age, int sex); ~Person(); public: friend void showPersonInfo(Person *person); // 將showPersonInfo()函數聲明為友元函數 };
person.cpp
#include "Person.h" Person::Person(char *name, int age, int sex) :m_name(name) , m_age(age) , m_sex(sex) { } Person::~Person() { }
運行結果:
xp.chen, age is: 20, sex is: 1
第二種場景
在某個類(假設為A類)有一個成員函數,該成員函數想去訪問另一個類(假設為B類)中的私有成員變量。這時候則可以在第二個類(B類)中,聲明第一個類(A類)的那個成員函數為友元函數,這樣第一個類(A類)就可以訪問第二個類(B類)的私有成員變量了。
例:打印Person類的詳細信息(包含姓名,年齡,性別,省份,城市,街道)
Person.h
#pragma once class Address; class Person { private: char *m_name; int m_age; int m_sex; public: Person(char *name, int age, int sex); ~Person(); public: void showDetailInfo(Address *addr); // 用於打印包含姓名,年齡,性別,省份,城市,街道的詳細信息 };
Address.h
#pragma once #include "Person.h" class Address { private: char *m_province; char *m_city; char *m_district; public: Address(char *province, char *city, char *district); ~Address(); public: friend void Person::showDetailInfo(Address *addr); };
Address.cpp
#include "Address.h" Address::Address(char *province, char *city, char *district) :m_province(province) , m_city(city) , m_district(district) { } Address::~Address() { }
Person.cpp
#include <iostream> #include "Address.h" Person::Person(char *name, int age, int sex) :m_name(name) , m_age(age) , m_sex(sex) { } void Person::showDetailInfo(Address *addr) { std::cout << "Name: " << m_name << ", Age: " << m_age << ", Sex: " << m_sex << ", Province: " << addr->m_province << ", City: " << addr->m_city << ", District: " << addr->m_district << std::endl; } Person::~Person() { }
main.cpp
#include <iostream> #include <stdlib.h> #include "Address.h" int main() { Person *person = new Person("xp.chen", 20, 1); Address *address = new Address("JS", "KS", "ZhengRoad"); person->showDetailInfo(address); delete person, address; system("pause"); return 0; }
運行結果:
Name: xp.chen, Age: 20, Sex: 1, Province: JS, City: KS, District: ZhengRoad
友元類
友元類則更簡單,可以將一個類(類A)聲明成另一個類(類B)的友元類,那么類A就擁有了能夠訪問類B所有成員的資格,包括private, protected, public的。
例:將上述例子中的Address.h修改成:
#pragma once #include "Person.h" class Address { private: char *m_province; char *m_city; char *m_district; public: Address(char *province, char *city, char *district); ~Address(); public: friend class Person; };
聲明類Person是類Address的友元類,再次運行程序:
Name: xp.chen, Age: 20, Sex: 1, Province: JS, City: KS, District: ZhengRoad
需要注意的是:
- 友元的關系是單向的而不是雙向的。如果聲明了類 B 是類 A 的友元類,不等於類 A 是類 B 的友元類,類 A 中的成員函數不能訪問類 B 中的 private 成員。
- 友元的關系不能傳遞。如果類 B 是類 A 的友元類,類 C 是類 B 的友元類,不等於類 C 是類 A 的友元類。
另外,有的編譯器也可以不寫class關鍵字,也就是說可以寫成:friend Person, 不過為了兼容性還是建議寫上。
