【C++ 筆記】Friend Classes & Functions - part 19
===
目錄(Table of Contents):
[TOC]
---
很感謝你點進來這篇文章。
你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧!
Friend Class
---
Friend Class 可以直接存取其他 class 的 private、protected 成員,只要當這個 class 被宣告為 `friend`。
因為 private、protected 成員不能直接存取,所以可以用 friend 的方式指定某 class 為好友 class,這在某些時候會變得很好用,如常見的 Data Structure:Linked-list。
宣告一個 friend class 格式如下:
```cpp
friend class class_name; // declared in the base class
```
以下是個範例:
```cpp=
#include <iostream>
using namespace std;
class Base {
private:
int privateValue = 10;
protected:
int protectedValue = 20;
public:
// 宣告 FriendClass 為朋友類別
friend class FriendClass;
void showBase() {
cout << "From Base: private=" << privateValue
<< ", protected=" << protectedValue << endl;
}
};
class FriendClass {
public:
void accessBase(Base& b) {
// 可直接存取 Base 的 private 和 protected 成員
cout << "From FriendClass: private=" << b.privateValue
<< ", protected=" << b.protectedValue << endl;
// 也可修改這些成員
b.privateValue = 100;
b.protectedValue = 200;
}
};
int main() {
Base baseObj;
FriendClass friendObj;
cout << "原始值:" << endl;
baseObj.showBase();
friendObj.accessBase(baseObj);
cout << "修改後的值:" << endl;
baseObj.showBase();
return 0;
}
```
輸出結果:
```
原始值:
From Base: private=10, protected=20
From FriendClass: private=10, protected=20
修改後的值:
From Base: private=100, protected=200
```
由上例可知:通常 friend 都宣告在要指定 friend 的 class 裡面,之後在外面額外宣告一個 friend class,從而存取 Base Class 裡面的成員。
總之,以上範例具有以下四種意義:
1. `Base` class 透過 `friend class FriendClass` 宣告將 `FriendClass` 設為朋友類別
2. `FriendClass` 可以直接存取 `Base` 的 `private` 和 `protected` 成員
3. 除存取外,也能直接修改這些成員。
4. 原本 private 和 protected 成員無法直接從外部存取,僅能透過 friend 關係才可直接存取
Friend Function
---
功能基本上跟 Friend Class 相同,但要注意 Friend Function 並不是類別中的成員函數,還是能跟 Friend Class 一樣存取 private、protected。
Friend Function 可為:
1. 全域函數(Global Function):字面上意思,就是"全域"函數。
2. 別的 Class 中的成員函數(Member Function)
以下是其格式:
```cpp=
friend return_type function_name (arguments); // for a global function
or
friend return_type class_name::function_name (arguments); // for a member function of another class
```
以下是個範例(Global Function):
```cpp=
#include <iostream>
using namespace std;
class Base {
private:
int privateValue = 10;
protected:
int protectedValue = 20;
public:
// 宣告 FriendClass 為朋友類別
friend class FriendClass;
// 宣告朋友函數
friend void friendFunction(Base& b);
void showBase() {
cout << "From Base: private=" << privateValue
<< ", protected=" << protectedValue << endl;
}
};
class FriendClass {
public:
void accessBase(Base& b) {
cout << "From FriendClass: private=" << b.privateValue
<< ", protected=" << b.protectedValue << endl;
b.privateValue = 100;
b.protectedValue = 200;
}
};
// 朋友函數的定義(不是任何類別的成員)
void friendFunction(Base& b) {
cout << "From friendFunction: private=" << b.privateValue
<< ", protected=" << b.protectedValue << endl;
// 同樣可以修改 private 和 protected 成員
b.privateValue = 300;
b.protectedValue = 400;
}
int main() {
Base baseObj;
FriendClass friendObj;
cout << "原始值:" << endl;
baseObj.showBase();
friendObj.accessBase(baseObj);
cout << "經 FriendClass 修改後:" << endl;
baseObj.showBase();
friendFunction(baseObj);
cout << "經 friendFunction 修改後:" << endl;
baseObj.showBase();
return 0;
}
```
輸出結果:
```
原始值:
From Base: private=10, protected=20
From FriendClass: private=10, protected=20
經 FriendClass 修改後:
From Base: private=100, protected=200
From friendFunction: private=100, protected=200
經 friendFunction 修改後:
From Base: private=300, protected=400
```
在上個範例 Friend Class 的基礎下,新增了 Friend Function,可見功能仍相同。
以下是第二個範例(member function of another class):
Source:https://www.geeksforgeeks.org/friend-class-function-cpp/
```cpp=
// C++ program to create a member function of another class
// as a friend function
#include <iostream>
using namespace std;
class base; // forward definition needed (需要在 anotherClass 前面定義)
// another class in which function is declared
class anotherClass {
public:
void memberFunction(base& obj); // 這裡跟 base class 有關
};
// base class for which friend is declared
class base {
private:
int private_variable;
protected:
int protected_variable;
public:
base()
{
private_variable = 10;
protected_variable = 99;
}
// friend function declaration (朋友函數宣告)
friend void anotherClass::memberFunction(base&);
};
// friend function definition
void anotherClass::memberFunction(base& obj)
{
cout << "Private Variable: " << obj.private_variable
<< endl;
cout << "Protected Variable: " << obj.protected_variable;
}
// driver code
int main()
{
base object1;
anotherClass object2;
object2.memberFunction(object1);
return 0;
}
```
輸出結果:
```
Private Variable: 10
Protected Variable: 99
```
### Friend Function 注意事項
---
* 關鍵字「friend」僅放在 Friend Function 的函數宣告中,而不放在函數定義或呼叫中。
* Friend Function 的呼叫方式與普通函數類似。不能用物件名稱和點運算子 "." 來呼叫它。但它可接受該物件作為它想要存取其值的參數。
* Friend Function可以在類別的任何部分宣告,即在 public、private、protected 都可。
* 定義另一個類別的 Friend Function 的順序很重要。必須要在函數定義之前定義兩個 class。這就是為什麼用類別外成員函數定義的原因。
參考資料
---
[friend 函式、friend 類別](https://openhome.cc/Gossip/CppGossip/friendFunctionClass.html)
[Friend Class and Function in C++ - GeeksforGeeks](https://www.geeksforgeeks.org/friend-class-function-cpp/)
[friend (C++) | Microsoft Learn](https://learn.microsoft.com/zh-tw/cpp/cpp/friend-cpp?view=msvc-170)
[C++ 友元函数 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-friend-functions.html)