【C++ 筆記】Friend Classes & Functions - part 19

很感謝你點進來這篇文章。

你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧!

Friend Class

Friend Class 可以直接存取其他 class 的 private、protected 成員,只要當這個 class 被宣告為 friend

因為 private、protected 成員不能直接存取,所以可以用 friend 的方式指定某 class 為好友 class,這在某些時候會變得很好用,如常見的 Data Structure:Linked-list。

宣告一個 friend class 格式如下:

1
friend class class_name; // declared in the base class

以下是個範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#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;
}

輸出結果:

1
2
3
4
5
原始值:
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 可以直接存取 Baseprivateprotected 成員
  3. 除存取外,也能直接修改這些成員。
  4. 原本 private 和 protected 成員無法直接從外部存取,僅能透過 friend 關係才可直接存取

Friend Function

功能基本上跟 Friend Class 相同,但要注意 Friend Function 並不是類別中的成員函數,還是能跟 Friend Class 一樣存取 private、protected。

Friend Function 可為:

  1. 全域函數(Global Function):字面上意思,就是”全域”函數。
  2. 別的 Class 中的成員函數(Member Function)

以下是其格式:

1
2
3
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):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#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;
}

輸出結果:

1
2
3
4
5
6
7
8
原始值:
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/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 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;
}

輸出結果:

1
2
Private Variable: 10
Protected Variable: 99

Friend Function 注意事項


  • 關鍵字「friend」僅放在 Friend Function 的函數宣告中,而不放在函數定義或呼叫中。
  • Friend Function 的呼叫方式與普通函數類似。不能用物件名稱和點運算子 “.” 來呼叫它。但它可接受該物件作為它想要存取其值的參數。
  • Friend Function可以在類別的任何部分宣告,即在 public、private、protected 都可。
  • 定義另一個類別的 Friend Function 的順序很重要。必須要在函數定義之前定義兩個 class。這就是為什麼用類別外成員函數定義的原因。

參考資料

friend 函式、friend 類別

Friend Class and Function in C++ - GeeksforGeeks

friend (C++) | Microsoft Learn

C++ 友元函数 | 菜鸟教程