---
# System prepended metadata

title: '● C++  Chapter 3 ,9,10'

---


## ● Chapter 1 #self-review exercises 1.3 (based on object oriented)
1. a) Objects have the property of ==**information hiding**== —although objects may know how to communicate with one another across well-defined interfaces, they normally are not allowed to know how other objects are implemented. 
2. b) C++ programmers concentrate on creating ==**classes**==, which contain data members and the member functions that manipulate those data members and provide services to clients. 
3. c) The process of analyzing and designing a system from an object-oriented point of view is called ==**object-oriented analysis and design (OOAD)**==. 
4. d) With **==inheritance==**, new classes of objects are derived by absorbing characteristics of existing
classes, then adding unique characteristics of their own.
5. e) ==**The Unified Modeling Language (UML)**== is a graphical language that allows people who design software systems to use an industry-standard notation to represent them.
6. f) The size, shape, color and weight of an object are considered of the object’s class ==**attribute**==.

---

# ● Chapter 3 classes,member functions and objects 

:::info
### 課本內容&範例:
:::
### ○ 3.1 Introduce
    
> chapter 3 為 oop(object orientated program)的入門簡介，於此章中討論下列幾種型態和其使用方式:
> - classes 類別
> - objects 物件
> - data members(attribute) 成員資料(屬性)
> - member functions(behaviors) 成員函式
### ○ 3.2 在c++中的 class 宣告與基本應用
__以一個存取可存取銀行帳戶和餘額的程式為範例:__
``` C++
1 // Fig. 3.1: AccountTest.cpp
2 // Creating and manipulating an Account object.
3 #include <iostream>
4 #include <string>
5 #include "Account.h"
6
7 using namespace std;
8
9 int main() {
10 Account myAccount; // create Account object myAccount
11
12 // show that the initial value of myAccount's name is the empty string
13 cout << "Initial account name is: " << myAccount.getName();
14
15 // prompt for and read name
16 cout << "\nPlease enter the account name: ";
17 string theName;
18 getline(cin,theName);
19 myAccount.setName(the Name)
20
21 // display the name stored in object myAccount
22 cout << "Name in object myAccount is: "
23 << myAccount.getName() << endl;
24 }
```
>由上方的 AccountTest.cpp 中，除了主要負責輸出輸入資料的getline()和cout外，我們可以在**第10行**的地方看到一個物件的宣告
```c++
10 Account myAccount; // create Account object myAccount
```
>此為主程式中宣告物件，可用於調用class中的成員資料與函式，此功能多用於在大型專案中需重複調用的資料、變數與函式等方面。那麼class的內容應該寫在哪裡? 有兩種方法:
1. 在int main(){}外與任何函式prototype外
2. 在檔案資料夾中新建一個檔案並以 .h 為副檔名

在fig.3.1中使用第二種方式，若要使用此行形式來編寫，則需在程式最上方使用header ==#include<"類別.h">== 來導入物件，在fig.3.1中的**第5行**:
```C++
5 #include<"Account.h">
```

__而在Account.h中，我們需要像fig.3.2一樣編寫一個完整的class__

```C++
1 // Fig. 3.2: Account.h
2 // Account class that contains a name data member
3 // and member functions to set and get its value.
4 #include <string> // enable program to use C++ string data type
5
6 class Account {
7 public:
8 // member function that sets the account name in the object
9 void setName(std::string accountName) {
10 name = accountName; // store the account name
11 }
12
13 // member function that retrieves the account name from the object
14 std::string getName() const {
15 return name; // return name's value to this function's caller
16 }
17 private:
18 std::string name; // data member containing account holder's name
19 }; // end class Account
```
>在.h的檔案裡如果會用到的內建函式，還是得先將它#include進來。接著便可以使用 ==class{...};== 的樣式來宣告一個類別 (:warning:和上學期教的結構一樣需在宣告完成後結尾加上分號;)。在類別中的物件又可分為 ==public:== 以及 ==private:== 兩種類別(fig.3.2第7行與第17行)。差別在於其作用域:
- public: 任何函數內只要有宣告類別物件便可使用，多為函式，即為 member functions。
- private: 只能在class內使用，多為變數型態，為 data member(attribute) 屬性物件的一種。

>此外，在主程式中調用類別函式則需以 ==類別物件名.函式名(參數)== 的形式來做呼叫。如fig.3.1中的:
```c++
myAccount.getName()
myAccount.setName(the Name)
```
>可分別對應到fig.3.2中的 ==getName(){}== 和 ==setName(){}== 。
setName()將提供的parameter(即為the Name)設定為private中的Name作為data member並可以getName()回傳其值。

__我們也可以以不同的類別物件來儲存不同的值，在此範例中作為儲存不同帳號資訊:__
```C++
1 Account myAccount1;
2 Account myAccount2;
3 myAccount1.setName("Epstien");
4 myAccount2.setName("Trump");
5 cout << myAccount1.getName() << "," <<endl;
6 cout << myAccount2.getName() << endl;
```
__由此，我們可以得到不同帳戶的資訊:__

 :::success
 __輸出:__
 Epstien,
 Trump
 :::
 ### ○ 3.4 使用Constructors初始化類別
 在上一個章節的範例中，我們使用 setName() 來初始化 data member 的值，但往往有些題目會在宣告類別物件時就將後面括號裡的 parameter 設為初始化data member的值。那麼在這種情況下，我們就必須使用default constructor 來初始化data member。
 ```C++
 // Fig. 3.4: Account.h
2 // Account class with a constructor that initializes the account name.
3 #include <string>
4
5 class Account {
6 public:
7 // constructor initializes data member name with parameter accountName
8 explicit Account(string accountName){ //explicit可加可不加，大多數編譯器會自行識別
9    name = accountName; //初始化member
10 }
11
12
13 // function to set the account name
14 void setName(string accountName) {
15 name = accountName;
16 }
17
18 // function to retrieve the account name
19 string getName() const {
20 return name;
21 }
22 private:
23 string name; // account name data member
24 }; // end class Account
 ```
如上方fig.3.4所展示，我們可以將Account.h的內容改成這樣，在第8~10行中，
```c++
8 explicit Account(string accountName){ //explicit可加可不加，大多數編譯器會自行識別
9    name = accountName; //初始化member
10 }
```
就是所謂的 ==default constructor==，我們只需在 int main() 裡宣告類別時寫上
```c++
Account myAccount("nigerian");
```
便可得到和setName()函式一樣的效果。
當然，我們仍舊可以使用原本的方法，不在宣告類別時加上parameter並使用member function:
```C++
Account myAccount;
myAccount.setNmae("nigerian");
```
### ○ 3.5 Get 和 Set 成員函式的應用

在之前的章節中，我們在class中都可以見到有兩種一定存在的 member functions，那便是 ==*get*== 和 ==*set*== 函式，這兩者可以用來修改 private 中的資料並控制其回傳的形式，我們也可以根據其作用來分別兩者:
- ***set*** : 多用於初始化、設定及修改 data members 的值，並且經常加上判斷式來篩選parameter的範圍 (e.g. fig.3.2 setName( ) )。
- ***get*** : 多用於回傳資料及輸出，也可以加上不同的判斷式來限定輸出的形式 (e.g. fig.3.2 getName( ) ) 。

==:information_source: 在一個class內，絕大多數的情況都會為每個data members 設置一組 set & get 函式==

### ○ 3.6 基礎class總範例 : 銀行帳戶資訊及餘額應用完整設定
```C++
1 // Fig. 3.8: Account.h
2 // Account class with name and balance data members, and a
3 // constructor and deposit function that each perform validation.
4 #include <string>
5
6 class Account {
7 public:
8 // Account constructor with two parameters
9 Account(std::string accountName,int initialBalance )
10 { // assign accountName to data member name
11     name = accountName;
12 // validate that the initialBalance is greater than 0; if not,
13 // data member balance keeps its default initial value of 0
14     if(initialBalance > 0){
15         balance = initialBalance;
16     }
17 }
18
19 // function that deposits (adds) only a valid amount to the balance
20 void deposit(int depositAmount) {
21     if (depositAmount > 0) { // if the depositAmount is valid
22         balance = balance + depositAmount; // add it to the balance
23     }
24 }
25
26 // function returns the account balance
27 int getBalance() const{
28     return Balance;
29 }
30
31 // function that sets the name
32 void setName(std::string accountName) {
33 name = accountName;
34 }
35
36 // function that returns the name
37 std::string getName() const {
38 return name;
39 }
40 private:
41 std::string name; // account name data member
42 int balance = 0;
43 }; // end class Account
```
由上列程式碼fig.3.8中，我們可以將其整理成幾個重點:
1. 在第9行到第17行中，可以明顯地看到 default constructor 內含有兩個參數，並使用if判斷式來限定帳戶餘額的數值。
2. 20行的void deposit()存入函式作為member function為set函式的一種，原因在於其修改了 private data 的值。
3. 此程式為每個data members 皆設置了 *set* 和 *get* 函式

接著，我們看到主程式的代碼 fig.3.9:
```C++
1 // Fig. 3.9: AccountTest.cpp
2 // Displaying and updating Account balances.
3 #include <iostream>
4 #include "Account.h"
5
6 using namespace std;
7
8 int main()
9 {
10    Account account1{"Jane Green", 50};
11    Account account2{"John Blue", -7};
12
13 // display initial balance of each object
14 cout << "account1: " << account1.getName() << " balance is $"
15 << account1.getBalance();
16 cout << "\naccount2: " << account2.getName() << " balance is $"
17 << account2.getBalance();
18
19 cout << "\n\nEnter deposit amount for account1: "; // prompt
20 int depositAmount;
21 cin >> depositAmount; // obtain user input
22 cout << "adding " << depositAmount << " to account1 balance";
23 Account account2{"John Blue", -7};
24
25 // display balances
26 cout << "\n\naccount1: " << account1.getName() << " balance is $"
27 << account1.getBalance();
28 cout << "\naccount2: " << account2.getName() << " balance is $"
29 << account2.getBalance();
30
31 cout << "\n\nEnter deposit amount for account2: "; // prompt
32 cin >> depositAmount; // obtain user input
33 cout << "adding " << depositAmount << " to account2 balance";
34 account2.deposit(depositAmount); // add to account2 balance
35
36 // display balances
37 cout << "\n\naccount1: " << account1.getName() << " balance is $"
38 << account1.getBalance();
39 cout << "\naccount2: " << account2.getName() << " balance is $"
40 << account2.getBalance() << endl;
41 }
```
根據上方程式和之前所提到的內容，輸出應為:
:::success
 *account1* : Jane Green balance is **$50**
 *account2* : John Blue balance is **$0**

 Enter deposit amount for account1: **25**
 adding **25** to account1 balance

*account1* : Jane Green balance is **$75**
*account2* : John Blue balance is **$0**

Enter deposit amount for account2: **123**
adding **123** to account2 balance

*account1* : Jane Green balance is **$75**
*account2* : John Blue balance is **$123**
:::
:::info
### 範例題型&解答:
:::
### ○ #self-review exercises 3.1 
1. a) Every class definition contains the keyword ==**class**== followed immediately by the
class’s name.
2. b) Class names, member-function names and data-member names are all ==**identifiers**==.
3. c) Each parameter in a function header specifies both a(n) ==**type**== and a(n) ==**name**==
4. d) Classes are *executed* by an instance of a class known as a(n) ==**object**==. 
5. e) Access specifiers are always followed by a **==colon==**. 
6. f) The private access specifier is the  **==default==** access specifier unless another is specified. 
7. g) When C++ implicitly calls a function of the class, then that function is known as the class’s ==**default constructor**==.
8. h) Any file that uses a class can include the class’s header via a(n) ==**# include**== preprocessing directive.
---

### ○ #self-review exercises 3.2
1. a) You can call a member function of a class even if an object of that class has not been created.  ==F==
2. b) Empty parentheses following a function name in a function definition indicate that the function does not require any parameters to perform its task. ==T==
3. c) If you define a custom constructor for a class, the compiler will not create a default constructor for that class. ==T==
4. d) Variables declared in the body of a particular member function are known as data members and can be used in all member functions of the class. ==F==
5. e) A header that you define in your program is placed in angle brackets (<>). ==F==
6. f) A constructor is a special member function that must have the same name as the class. ==T==
---

### ○ Chapter 3 #Exercises 
>**3.10**
Modify class Account to provide a member function
called withdraw that withdraws money from an Account. Ensure that the withdrawal amount does
not exceed the Account’s balance. If it does, the balance should be left unchanged and the member
function should display a message indicating "Withdrawal amount exceeded account balance."
Modify class AccountTest to test member function withdraw.
```C++
#include <iostream>
//using namespace std; here if you don't wanna type std:: shitty stuff below
class Account {
private:
    int balance;

public:
    // Constructor initializes balance
    Account(int initialBalance) {
        if (initialBalance >= 0) {
            balance = initialBalance;
        } else {
            balance = 0;
            std::cout << "Error: Initial balance cannot be negative. Setting balance to 0." << std::endl;
        }
    }

    // Function to add money to the account
    void credit(int amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    // Function to withdraw money from the account
    void withdraw(int amount) {
        if (amount > balance) {
            std::cout << "Withdrawal amount exceeded account balance." << std::endl;
        } else if (amount > 0) {
            balance -= amount;
        }
    }

    // Function to return the current balance
    int getBalance() const {
        return balance;
    }
};

// AccountTest class/main function to test the Account class
int main() {
    // 1. Initialize two accounts with starting balances
    Account account1(50);
    Account account2(100);

    // Display initial balances
    std::cout << "Initial account1 balance: $" << account1.getBalance() << "\n";
    std::cout << "Initial account2 balance: $" << account2.getBalance() << "\n\n";

    // 2. Test a valid withdrawal (Amount < Balance)
    int withdrawalAmount1 = 25;
    std::cout << "Attempting to withdraw $" << withdrawalAmount1 << " from account1...\n";
    account1.withdraw(withdrawalAmount1);
    std::cout << "account1 balance is now: $" << account1.getBalance() << "\n\n";

    // 3. Test an invalid withdrawal (Amount > Balance)
    int withdrawalAmount2 = 60;
    std::cout << "Attempting to withdraw $" << withdrawalAmount2 << " from account1...\n";
    account1.withdraw(withdrawalAmount2);
    std::cout << "account1 balance is still: $" << account1.getBalance() << "\n\n";

    // 4. Test another valid withdrawal on the second account
    int withdrawalAmount3 = 100;
    std::cout << "Attempting to withdraw $" << withdrawalAmount3 << " from account2...\n";
    account2.withdraw(withdrawalAmount3);
    std::cout << "account2 balance is now: $" << account2.getBalance() << "\n";

    return 0;
} 
```

---
## ● Chapter 9 A deeper look
:::info
### 課本內容&範例
:::
### ○ 9.1 Introduction
在這個章節中，我們會以Time, Date and Employee類型的class範例來展示一些關於class的進階用法。在此之前，我們先複習該如何調用public中的成員函式:
 - 物件名稱加上點運算子 (.)
 - 物件的參照加上點運算子 (.)
 - 物件的指標加上箭頭運算子 (->)
### ○ 9.2 Time 類別案例:從類別檔案內分離執行函式

先前第三章中的 class 宣告的範例裡，我們都會先新創一個.h檔案專門放置class的內容，接著在main中以header的形式將.h檔include進來。但是，此種作法是非常危險的，設置在header代表它是所有人都可以任意打開文檔。所以對主程式而言只需要知道:
 - 需要調用的成員函式
 - 提供給各函式的參數
 - 函式所回傳的資料型別
 
藉由這些條件，我們可以簡單的設計一個表示時間的類別 Time.h，請務必注意，在寫入member functions時，我們只需要宣告他們的prototypes即可。此外，我們可以在類別的前後分別加上 ==#ifndef TIME_H== 、 ==#define TIME_H== 和 ==#endif== 這些稱為 ==include guard== 的東西來預防多次調用。如下列 fig.9.1 所示:
```C++
1 // Fig. 9.1: Time.h
2 // time class defintion.
3 // member functions are define in Time.cpp.
4 #include <string>
5
6 // prevent multiple inclusions of header
7 #ifndef TIME_H
8 #define TIME_H
9
10 // Time class definition
11 class Time {
12 public:
13 void setTime(int, int, int); // set hour, minute and second
14 std::string toUniversalString() const; // 24-hour time format string
15 std::string toStandardString() const; // 12-hour time format string
16 private:
17 unsigned int hour{0}; // 0 - 23 (24-hour clock format)
18 unsigned int minute{0}; // 0 - 59
19 unsigned int second{0}; // 0 - 59
20 };
21
22 #endif
```
我們在Time.h裡只寫入prototypes，代表我們需要將函式運作的內容放在另一個非主程式的Time.cpp中來完成可多次調用且分離主程式介面的特性。如 fig.9.2 所示:
```C++
1 // Fig. 9.2:
2 // Time class member-function defintions
3 #include <iomanip> // for setw and setfill stream manipulators
4 #include <stdexcept> // for invalid_argument exception class
5 #include <sstream> // for ostringstream class
6 #include <string>
7 #include "Time.h" //include defintions of class from Time.h
8
9 using namespace std;
10
11 // set new Time value using universal time
12 void Time::setTime(int h, int m, int s) {
13 // validate hour, minute and second
14 if ((h >= 0 && h < 24) && (m >= 0 && m < 60) && (s >= 0 && s < 60)) {
15     hour = h;
16     minute = m;
17     second = s;
18 }
19 else {
20        throw invalid_argument(
21        "hour, minute and/or second was out of range");
22     }
23 }
24
25 // return Time as a string in universal-time format (HH:MM:SS)
26 string Time::toUniversalString() const {
27     ostringstream output;
28     output << << setw(2) << hour << ":"
29     << setw(2) << minute << ":" << setw(2) << second;
30     return output.str(); //return the format string
31 }
32
33 // return Time as string in standard-time format (HH:MM:SS AM or PM)
34 string Time::toStandardString() const {
35     ostringstream output;
36     output << ((hour == 0 || hour == 12) ? 12 : hour % 12) << ":"
37     << setfill('0') << setw(2) << minute << ":" << setw(2)
38     << second << (hour < 12 ? " AM" : " PM");
39     return output.str();
40 }
```
這段程式將所有member functions的功能寫下，其中除了邏輯判斷和運算外還需特別注意Get函式格式化輸出return形式的寫法，如 fig.9.2 中的 toUniversalString( ):
```C++
26 string Time::toUniversalString() const {
27     ostringstream output;
28     output << << setw(2) << hour << ":"
29     << setw(2) << minute << ":" << setw(2) << second;
30     return output.str(); //return the format string
31 }
```
:::warning 
#### :warning: 注意
首先宣告 output 變數為 ostringstream 型態 (為一種字串流的datatype)，接著再如cout一樣調用 iomanip 中的函數進行格式化排版，最後只需回傳 output.str() 便可回傳格式化輸出的字串。
:::
在做完這些程序後，我們最後來看到主程式main.cpp的寫法並做出一寫簡單的測試，如同 fig.9.3:
```C++
1 // Fig. 9.3: fig09_03.cpp
2 // program to test class Time
3 // Note: This file must be compiled with Time.cpp
4 #include <iostream>
5 #include <stdexcept> // invalid_argument exception class
6 #include"Time.h" //其實這裡可替換成 #include"Time.cpp"
7 using namespace std;
8
9 // displays a Time in 24-hour and 12-hour formats
10 void displayTime(const string& message, const Time& time) {
11     cout << message << "\nUniversal time: " <<
12     << "\nStandard time: " << << "\n\n";
13 }
14
15 int main() {
16     Time t; // instantiate object t of class Time
17
18     displayTime("Initial time:", t); // display t's initial value
19     t.setTime(13, 27, 6); // change time
20     displayTime("After setTime:", t); // display t's new value
21
22     // attempt to set the time with invalid values
23     try {
24         t.setTime(99,99,99)// all values out of range
25     }
26     catch (invalid_argument& e) {
27         cout << "Exception: " << e.what() << "\n\n";
28     }
29
30     // display t's value after attempting to set an invalid time
31     displayTime("After attempting to set an invalid time:", t);
32 }
```
根據輸入的測資，我們可以得到以下結果:
:::success
Initial time:
Universal time: **00:00:00**
Standard time: **12:00:00 AM**
After setTime:
Universal time: **13:27:06**
Standard time: **1:27:06 PM**
**Exception: hour, minute and/or second was out of range**
After attempting to set an invalid time:
Universal time: **13:27:06**
Standard time: **1:27:06 PM**
:::
### ○ 9.3 編譯和連結過程之圖示
若你已經理解上述程式的知行以及header間的連結與，我們可以將這些過程整理成一張圖示(課本438頁 fig.9.4):
![image](https://hackmd.io/_uploads/ryQrbZRiWl.png)
### ○ 9.4 class 的作用域與取得 member functions

我們在此先複習9.1中提到的取得類別中 member functions 的幾種寫法:
 - 物件名稱加上點運算子 (.)
 - 物件的參照加上點運算子 (.)
 - 物件的指標加上箭頭運算子 (->)
 
接著我們來以一些範例示範:
```C++
1 Account account; // an Account object
2 // accountRef refers to an Account object
3  Account& accountRef{account};
4 // accountPtr points to an Account object
5 Account* accountPtr{&account};
6 // call setBalance via the Account object
7 account.setBalance(123.45);
8 // call setBalance via a reference to the Account object
9 accountRef.setBalance(123.45);
10 // call setBalance via a pointer to the Account object
11 accountPtr->setBalance(123.45);
```
前三組為宣告物件的不同方法，結果皆一樣，分別是直接宣告、使用參照形式宣告以及使用指標形式宣告。後三組則為上述所提及的調用 member function 的三種不同寫法。
### ○ 9.6 Time 類別範例 : 多種不同參數位置的 default constructor
在第三章中，我們學了該如何使用 default constructor 來初始化資料，那今日如果有一程式以各種不同位置及參數值輸入來嘗試初始化如下列:
```C++
Time t1; 
Time t2{2}; 
Time t3{21, 34};  
Time t4{12, 25, 42};
```
這時我們又該從何開始做變化呢?
一樣的步驟，先創立Time.h檔來存取member functions的prototypes，如 fig.9.5。
```C++
1 // Fig. 9.5: Time.h
2 // Time class containing a constructor with default arguments.
3 // Member functions defined in Time.cpp.
4 #include <string>
5
6 // prevent multiple inclusions of header
7 #ifndef TIME_H
8 #define TIME_H
9
10 // Time class definition
11 class Time {
12 public:
13    explicit Time(int = 0, int = 0, int = 0); // default constructor
14
15     // set functions
16     void setTime(int, int, int); // set hour, minute, second
17     void setHour(int); // set hour (after validation)
18     void setMinute(int); // set minute (after validation)
19     void setSecond(int); // set second (after validation)
20
21     // get functions
22     unsigned int getHour() const; // return hour
23     unsigned int getMinute() const; // return minute
24     unsigned int getSecond() const; // return second
25
26     std::string toUniversalString() const; // 24-hour time format string
27     std::string toStandardString() const; // 12-hour time format string
28 private:
29     unsigned int hour{0}; // 0 - 23 (24-hour clock format)
30     unsigned int minute{0}; // 0 - 59
31     unsigned int second{0}; // 0 - 59
32 };
33
34 #endif
```
接著，一樣創建Time.cpp來存取member functions的功能:
```C++
#include <string>
7 #include "Time.h" // include definition of class Time from Time.h
8 using namespace std;
9
10 // Time constructor to intialize each data members
11 Time::Time(int hour,int minute,int second) {
12     setTime(hour,minute,second); // validate and set time
13 }
14
15 // set new Time value using universal time
16 void Time::setTime(int h, int m, int s) {
17     setHour(h); // set private field hour
18     setMinute(m); // set private field minute
19     setSecond(s); // set private field second
20 }
21
22 // set hour value
23 void Time::setHour(int h) {
24     if (h >= 0 && h < 24) {
25         hour = h;
26     }
27     else {
28         throw invalid_argument("hour must be 0-23");
29     }
30 }
31
32 // set minute value
33 void Time::setMinute(int m) {
34     if (m >= 0 && m < 60) {
35         minute = m;
36     }
37     else {
38         throw invalid_argument("minute must be 0-59");
39     }
40 }
41
42 // set second value
43 void Time::setSecond(int s) {
44     if (s >= 0 && s < 60) {
45         second = s;
46     }
47     else {
48         throw invalid_argument("second must be 0-59");
49     }
50 }
51
52 // return hour value
53 unsigned int Time::getHour() const {return hour;}
54
55 // return minute value
56 unsigned Time::getMinute() const {return minute;}
57
58 // return second value
59 unsigned Time::getSecond() const {return second;}
60
61 // return Time as a string in universal-time format (HH:MM:SS)
62 string Time::toUniversalString() const {
63     ostringstream output;
64     output << setfill('0') << setw(2) << getHour() << ":"
65     << setw(2) << getMinute() << ":" << setw(2) << getSecond();
66     return output.str();
67 }
68
69 // return Time as string in standard-time format (HH:MM:SS AM or PM)
70 string Time::toStandardString() const {
71     ostringstream output;
72     output << ((getHour() == 0 || getHour() == 12) ? 12 : getHour() % 12)
73     << ":" << setfill('0') << setw(2) << getMinute() << ":" << setw(2)
74     << getSecond() << (hour < 12 ? " AM" : " PM");
75     return output.str();
76 }
```
:::info
***此時，我們看到第11到13行的default constructor有了明顯的變化，
從原先的直接初始化data member到現在丟給分離開的set function來做初始化。***
:::
這樣一來，我們便能實施多參數位置變化輸入的功能。最後，我們將主程式 main.cpp 以之前的方式完成。(fig.9.7)
```C++
1 // Fig. 9.7: fig09_07.cpp
2 // Constructor with default arguments.
3 #include <iostream>
4 #include <stdexcept>
5 #include "Time.h" // include definition of class Time from Time.h
6 using namespace std;
7
8 // displays a Time in 24-hour and 12-hour formats
9 void displayTime(const string& message, const Time& time) {
10 cout << message << "\nUniversal time: " <<
11 << "\nStandard time: " << << "\n\n";
12 }
13
14 int main() {
15     Time t1; // all arguments defaulted
16     Time t2{2}; // hour specified; minute and second defaulted
17     Time t3{21, 34}; // hour and minute specified; second defaulted
18     Time t4{12, 25, 42}; // hour, minute and second specified
19
20     cout << "Constructed with:\n\n";
21     displayTime("t1: all arguments defaulted", t1);
22     displayTime("t2: hour specified; minute and second defaulted", t2);
23     displayTime("t3: hour and minute specified; second defaulted", t3);
24     displayTime("t4: hour, minute and second specified", t4);
25
26     // attempt to initialize t5 with invalid values
27     try {
28         Time t5{27, 74, 99}; // all bad values specified
29     }
30     catch (invalid_argument& e) {
31     cerr << "Exception while initializing t5: " << e.what() << endl;
32     }
33 }
```
如15至18行一樣以不同位置的參數來進行初始化，得到的結果如下:
:::success
Constructed with:
t1: all arguments defaulted
Universal time: 00:00:00
Standard time: 12:00:00 AM
t2: hour specified; minute and second defaulted
Universal time: 02:00:00
Standard time: 2:00:00 AM
t3: hour and minute specified; second defaulted
Universal time: 21:34:00
Standard time: 9:34:00 PM
t4: hour, minute and second specified
Universal time: 12:25:42
Standard time: 12:25:42 PM
Exception while initializing t5: hour must be 0-23
:::
### ○ 9.7 Destructors
destructor是一種特別的member function，通常以==波浪號(~)== 加上類別名稱來完成破壞此類別的指令。destructor被稱為 ==*implicitly*== 當物件被壞時，這邊的破壞並非釋放物件所占用的記憶體空間，而是終止清理動作直到物件再次被宣告之前。即使destructor不能被作為類別的必要成員，每個類別都至少會有一個destructor，所以如果你並未在類別內定義一個，編譯器會自動幫你生成一個空destructor。
### ○ 9.8 constructors 和 destructors 的呼叫使用範例
>destructor被使用在三種不同的作用域也會有不同的功能，分別為global, local 以及 local static objects of class，其差別如下
#### 1. 全域作用域物件 (Global Scope Objects)
    這指的是宣告在所有函式（包含 main）之外的物件。

- ***建構時機***： 在程式的任何函式（包含 main 函式）開始執行之前，建構子就會被呼叫。(注意：不同檔案間的全域物件，其建構順序是無法保證的。)

-  ***解構時機***： 當 main 函式正常結束時，解構子會被呼叫。

- ***強制終止的影響：***

    - 呼叫 ==exit 函式==：程式會立即終止，不會執行「區域物件」的解構子。通常用於發生無法挽回的致命錯誤時。

    - 呼叫 ==abort 函式==：程式會立刻異常終止，完全不允許執行任何清理動作（解構子皆不執行）。

#### 2. 非靜態區域物件 (Non-static Local Objects)
    這是最常見的狀況，也就是一般在函式或大括號 {} 區塊內部宣告的普通物件。

- ***建構時機***： 當程式執行到該物件被定義的該行程式碼時。

- ***解構時機***： 當程式執行離開該物件的作用域（例如該函式或區塊結束）時。

- ***特性***： 每次程式進入和離開該作用域時，建構子和解構子都會被對應地呼叫。

    - 強制終止的影響： 若程式因呼叫 exit 或 abort 而提前終止，這些區域物件的解構子都不會被執行。

#### 3. 靜態區域物件 (Static Local Objects)
    這是在函式內部宣告，但前面加了 static 關鍵字的物件。

- ***建構時機：*** 當程式第一次執行到該物件定義的地方時才會被呼叫，且整個程式執行期間只會建立一次。

- ***解構時機：*** 當 main 函式結束，或者是程式呼叫了 exit 函式時，解構子才會被呼叫。

- ***銷毀順序規則：*** 全域物件與靜態物件的銷毀順序，會與它們被建立的順序完全相反 (Reverse order)。也就是「晚建立的先銷毀」。

    - 強制終止的影響： 若程式因呼叫 abort 而終止，靜態物件的解構子不會被呼叫。

>接著，我們來看看一些範例(fig.9.8 ~ 9.10):
```C++
1 // Fig. 9.8: CreateAndDestroy.h
2 // CreateAndDestroy class definition.
3 // Member functions defined in CreateAndDestroy.cpp.
4 #include <string>
5
6 #ifndef CREATE_H
7 #define CREATE_H
8
9 class CreateAndDestroy {
10 public:
11 CreateAndDestroy(int, std::string); // constructor
12 ~CreateAndDestroy(); // destructor
13 private:
14 int objectID; // ID number for object
15 sdt::string message; // message describing object
16 };
17
18 #endif
```
```C++
1 // Fig. 9.9: CreateAndDestroy.cpp
2 // CreateAndDestroy class member-function definitions.
3 #include <iostream>
4 #include "CreateAndDestroy.h"// include CreateAndDestroy class definition
5 using namespace std;
6
7 // constructor sets object's ID number and descriptive message
8 CreateAndDestroy::CreateAndDestroy(int ID, string messageString)
9 : objectID{ID}, message{messageString} {
10 cout << "Object " << objectID << " constructor runs "
11 << message << endl;
12 }
13
14 // destructor
15 CreatAndDestroy::CreatAndDestroy(){
16 // output newline for certain objects; helps readability
17 cout << (objectID == 1 || objectID == 6 ? "\n" : "");
18
19 cout << "Object " << objectID << " destructor runs "
20 << message << endl;
21 }
```
```C++
1 // Fig. 9.10: fig09_10.cpp
2 // Order in which constructors and
3 // destructors are called.
4 #include <iostream>
5 #include "CreateAndDestroy.h" // include CreateAndDestroy class definition
6 using namespace std;
7
8 void create(); // prototype
9
10 CreateAndDestroy first{1, "(global before main)"}; // global object
11
12 int main() {
13     cout << "\nMAIN FUNCTION: EXECUTION BEGINS" << endl;
14     CreatAndDestroy second{2,"(local in main)"}
15     static CreateAndDestroy third{3, "(local static in main)"};
16
17     create(); // call function to create objects
18
19     cout << "\nMAIN FUNCTION: EXECUTION RESUMES" << endl;
20     CreateAndDestroy fourth{4, "(local in main)"};
21     cout << "\nMAIN FUNCTION: EXECUTION ENDS" << endl;
22 }
23
24 // function to create objects
25 void create() {
26     cout << "\nCREATE FUNCTION: EXECUTION BEGINS" << endl;
27     CreateAndDestroy fifth{5, "(local in create)"};
28     static CreateAndDestroy sixth{6, "(local static in create)"};
29     CreateAndDestroy seventh{7, "(local in create)"};
30     cout << "\nCREATE FUNCTION: EXECUTION ENDS" << endl;
31 }
```
:::warning
## :warning: 由於去给果乾4570回到宿舍感覺快猝死在電腦桌前，後面的內容(包括第十章)都丟給gemini幫我整理，可以對照課本閱讀確認，因為這傢伙沒有檢查輸出內容==。
:::
___
### ○ 9.9 傳回 private 資料成員的參照或指標 (A Subtle Trap)

>破壞封裝性 (Encapsulation)： 類別的資料成員通常設為 private 以保護資料不被隨意竄改。然而，如果 public 成員函式傳回了 private 變數的「參照 (Reference)」或「指標 (Pointer)」，呼叫端就可以透過該參照或指標，直接繞過類別的資料驗證機制（如 setter 內的 if 判斷）來修改內部資料。這是一個不容易察覺但非常危險的陷阱 (Subtle Trap)。

:computer: ***範例:***

```C++
// 假設 Time 類別有一個 private 變數 hour
int& badSetHour() { 
    return hour; // 錯誤示範：回傳了 private 變數的 reference
} 

// 客戶端程式呼叫
Time t;
t.badSetHour() = 74; // 外部可以直接把不合理的值指派給 private 變數
```
___
### ○ 9.10 預設成員逐一指派 (Default Memberwise Assignment)
#### 📌核心重點：

>自動指派： 你可以使用指派運算子 (=) 將一個物件指派給另一個「同型別」的物件。

>逐一指派 (Memberwise Assignment)： 預設情況下，編譯器會自動將右側物件的每一個成員變數，一模一樣地拷貝到左側物件對應的成員中。

>潛在風險： 這種複製屬於「淺層複製 (Shallow Copy)」。若類別內含有指向動態配置記憶體的指標成員，預設的指派會導致兩個物件的指標指向同一塊記憶體，在物件解構時可能引發嚴重的記憶體重複釋放錯誤。

#### 💻 範例：

```C++
Date date1(7, 4, 2004);
Date date2;
date2 = date1; // date2 的日、月、年變數會自動複製 date1 的值
```
___
### ○ 9.11 const 物件與 const 成員函式 (const Objects and const Member Functions)
#### 📌 核心重點：

>常數物件： 加上 const 關鍵字宣告的物件，其內部狀態在初始化後就「不允許被修改」。

>呼叫限制： const 物件只能呼叫被宣告為 const 的成員函式。因為編譯器無法保證非 const 函式是否會偷偷修改資料。

>語法： 在函式宣告和定義的參數列括號後方加上 const。

>注意： 建構子與解構子不能宣告為 const，因為建構子的任務本身就是去「初始化」（修改）物件的狀態。

#### 💻 範例：

```C++
class Time {
public:
    int getHour() const; // const 成員函式 (保證不修改狀態)
    void setHour(int);   // 非 const 函式 (會修改狀態)
};

const Time noon(12, 0, 0);
noon.getHour(); // 允許呼叫
// noon.setHour(13); // 編譯錯誤！const 物件不能呼叫非 const 函式
```
___
### ○ 9.12 合成：將物件作為類別的成員 (Composition)
#### 📌 核心重點：

>"Has-a" 關係： 一個類別可以包含其他類別的物件作為其資料成員，這種物件包含物件的技術稱為「合成 (Composition)」。

>成員初始化串列： 若內部的成員物件沒有「預設建構子 (Default Constructor)」，或者你需要傳遞特定的參數給它，就必須在外部類別建構子的成員初始化串列 (Member Initializer List) 中對它進行初始化，而不能在建構子的大括號 {} 內用指派的方式。

#### 💻 範例：

```C++
class Employee {
private:
    string firstName;
    Date birthDate; // Date 是另一個類別的物件
public:
    // 必須使用「成員初始化串列」來建構 birthDate
    Employee(string first, Date dob) : firstName(first), birthDate(dob) {
        // 建構子主體
    }
};
```
___
### ○ 9.13 friend 函式與 friend 類別 (friend Functions and friend Classes)
#### 📌 核心重點：

>突破存取權限： 在類別內使用 friend 關鍵字，可以授權一個「非成員函式」或「另一個類別」直接存取該類別的 private 與 protected 成員。

>三大特性：

>給予而非索取： 類別必須明確宣告誰是它的朋友，外部函式不能擅自宣告自己為朋友。

>不具對稱性： 類別 A 宣告 B 是朋友，並不代表 A 也是 B 的朋友。

>不具傳遞性： A 是 B 的朋友，B 是 C 的朋友，並不代表 A 是 C 的朋友。

#### 💻 範例：

```C++
class Count {
    friend void setX(Count&, int); // 授權友誼給 setX 函式
private:
    int x;
};

// setX 不是 Count 的成員函式，但可以直接存取 private 的 x
void setX(Count& c, int val) { 
    c.x = val; 
}
```
___
### ○ 9.14 使用 this 指標 (Using the this Pointer)
#### 📌 核心重點：

>隱含指標： 每個非 static 的成員函式在被呼叫時，編譯器都會隱含傳遞一個名為 this 的指標，它指向「呼叫該函式的物件本身」。

>解決名稱衝突： 當函式的參數名稱與類別的成員變數名稱相同時，可以使用 this-> 來明確指定類別的成員變數。

>串接函式呼叫 (Cascaded Function Calls)： 讓成員函式回傳物件本身的參照 (return *this;)，就能允許連續呼叫多個函式。

#### 💻 範例：

```C++
class Time {
private:
    int hour;
public:
    Time& setHour(int hour) {
        this->hour = hour; // this->hour 是成員變數，hour 是傳入的參數
        return *this;      // 回傳物件本身，以支援後續串接
    }
};

// 呼叫端可以串接使用：
// timeObject.setHour(12).setMinute(30);
```
___
### ○ 9.15 static 類別成員 (static Class Members)
#### 📌 核心重點：

>類別層級的共用資料： 當類別的所有實例物件都需要共用「同一個變數」時（例如：追蹤目前總共建立了幾個物件），應將其宣告為 static。

>獨立於物件存在： 即使程式中還沒有實例化任何物件，static 變數也已經存在記憶體中。若是 public 屬性，可直接透過 類別名稱::成員名稱 來存取。

>static 函式的限制： 宣告為 static 的成員函式沒有 this 指標，因此它絕對不能存取類別中非 static 的一般資料成員或函式。

>初始化位置： 通常 static 資料成員必須在類別定義的外部（通常在 .cpp 檔中）進行初始化。

#### 💻 範例：

```C++
class Employee {
private:
    static int count; // 靜態資料成員宣告
public:
    Employee() { count++; } // 每次建立物件時增加數量
    static int getCount() { return count; } // 靜態成員函式
};

// 在類別外部（.cpp 檔）進行全域初始化
int Employee::count = 0;
```

---

:::info
### 範例題型&解答
:::
### ○ #self-review exercises 9.1
1. a) Class members are accessed via the ==**dot(.)**== operator in conjunction with the name of an object (or reference to an object) of the class or via the ==**arrow(->)**== operator with a pointer to an object of the class.
operator in conjunc
2. b) The **==default constructor==** is a constructor that can be invoked with no arguments.
3. c) You can invoke the public member function of a class by using the **==dot(.)==** and operators ==**arrow(->)**==.
4. d) Functions that can read or display data, but cannot modify it are called **==access functions==**.
5. e) If a member function is defined in a class’s body, the member function is implicitly declared **==inline==**.
6. f) Using data members before they have been properly initialized can cause **==logic errors==**.
7. g) The calling constructor is known as a ==**delegating constructor**==.
8. h) Private member function that supports the operation of a class’s other member functions are known as **==utility functions==**.
9. i) Keyword ==*const*== specifies that an object or variable is not modifiable.
10. j) Constructors and destructors for **==non-static==** local objects are called each time execution enters and leave the scope of the object.
11. k) A class’s destructor is called **==implicitly==** when an object is destroyed.
12. l) Member objects are constructed **==before==** their enclosing class object.
13. m) **==Data integrity==** can be ensured by making data members private and controlling access,especially write access, to those data members through public member functions.
---

### ○ #self-review exercises 9.2
**Find the error(s) in each of the following and explain how to correct it (them):**

> a) Assume the following prototype is declared in class Time:

```cpp
void ~Time(int);
```
-  #Error : Destructors are not allowed to return values (or even specify a return type) or take arguments.  
- #Correction: Remove the return type void and the parameter int from the declaration.
---

> b) Assume the following prototype is declared in class Employee: 
```cpp
int Employee(string, string);
```
- #Error : Constructors are not allowed to return values.
- #Correction : Remove the return type int from the declaration.
- ---

> c) The following is a definition of class Example:
```cpp
class Example {
public:
 Example(int y = 10) : data(y) { }
 int getIncrementedData() const {
 return ++data; 
 } 
 static int getCount() {
 cout << "Data is " << data << endl;
 return count;
 } 
private:
 int data;
 static int count;
};
```
- #Error : The class definition for Example has two errors. The first occurs in function getIncrementedData. The function is declared const, but it modifies the object.
- #Correction : To correct the first error, remove the const keyword from the definition of  
getIncrementedData. *[Note: It would also be appropriate to rename this member function as get functions are typically const member functions.]*
---
# ● Chapter 10 : Operator Overloading; Class string
### ○ 10.2 使用標準函式庫 string 類別的多載運算子
-  #### 重點： 
    C++ 內建的 string 類別已經為我們預先多載了許多實用的運算子，使得字串操作能夠像基本型態 (如 int) 一樣直覺，而不需要使用傳統 C 語言的 strcpy 或 strcmp。
- #### 範例：
    - 使用 ==、!= 或 < 來比較字串字典序。
    - 使用 + 或 += 將兩個字串串接起來。
    - 使用 [] 透過索引值直接存取或修改字串中的特定字元。
    
- #### 程式範例：

```C++
#include <iostream>
#include <string>
using namespace std;

int main() {
    string s1 = "Hello";
    string s2 = "World";

    string s3 = s1 + " " + s2; // 多載 + (串接字串)
    cout << "s3: " << s3 << endl;

    if (s1 != s2) {            // 多載 != (比較內容)
        cout << "s1 和 s2 不相等" << endl;
    }

    s1[0] = 'h';               // 多載 [] (存取與修改單一字元)
    cout << "修改後的 s1: " << s1 << endl;

    return 0;
}
```
---
### 10.3 運算子多載基礎 (Fundamentals of Operator Overloading)
- #### 重點： 
     C++ 允許開發者賦予內建運算子（如 +, -, *, /）新的意義，讓它們能夠直接作用於「自訂的類別物件」上。
- #### 宣告方式： 
    使用 operator 關鍵字加上運算子符號，例如 operator+。

- #### 嚴格限制： 
    1. 不能創造新的運算子（例如不能發明 @ 運算子）。
    2. 不能改變運算子原有的「優先權 (Precedence)」、「結合性 (Associativity)」與「運算元個數 (Arity)」。

不能多載的運算子： 包括 . (成員存取)、.* (成員指標存取)、:: (作用域解析)、?: (條件運算子) 與 sizeof。

---

### 10.4 多載二元運算子 (Overloading Binary Operators)
- #### 重點： 
     二元運算子帶有兩個運算元（例如 A + B）。

    若定義為成員函式：左側運算元會隱含作為呼叫該函式的 this 物件，而右側運算元則作為函式的參數傳入。例如 A.operator+(B)。

    若定義為全域非成員函式：則必須傳入兩個參數。
---
#### 10.5 多載串流插入與串流擷取運算子 (<< 與 >>)
- #### 重點： 
    為了讓自訂物件能像內建型態一樣，直接使用 cout << obj 和 cin >> obj 進行輸出入。

    為什麼不能是成員函式？ 因為 cout << obj 的左側運算元是 ostream 類別的物件，右側才是我們的自訂物件。如果寫成成員函式，會變成荒謬的 obj << cout。

- #### 範例： 
    必須將它們宣告為類別的 全域 friend 函式。函式必須回傳 ostream& 或 istream& 以支援串聯呼叫（如 cout << a << b;）。
    ```C++
    friend ostream& operator<<(ostream& output, const PhoneNumber& number);
    ```

___

### 10.6 多載一元運算子 (Overloading Unary Operators)
- #### 重點： 
    一元運算子（如 !, ~, -）只有一個運算元。如果將其多載為類別的成員函式，它不需要任何參數，因為它只會作用於呼叫它的 this 指標所指向的物件本身。
___
### 10.7 多載遞增與遞減運算子 (++ 與 --)
- #### 重點： 
    ++ 和 -- 分為前置 (Prefix) 與後置 (Postfix)，編譯器需要機制來區分這兩者。

- #### 前置多載： 
    作為成員函式時不帶參數，通常回傳修改後物件的 reference。
    ```C++
    Date& operator++();
    ```
- #### 後置多載： 
    為了區分，C++ 規定後置版本的函式參數列必須加上一個無作用的整數 (dummy int)。後置運算子通常會先複製一份原始物件，將原物件遞增後，回傳修改前的副本 (傳值回傳)。
    ```C++
    Date operator++(int);
    ```
    ___
### 10.8 個案研究：Date 類別
- #### 重點： 
    課本透過實作一個 Date (日期) 類別，整合示範如何多載串流輸出 <<，以及如何實作複雜的 ++ 邏輯（包含跨月、判斷閏年、甚至跨年時的日期進位處理）。
    ___
### 10.9 動態記憶體管理 (Dynamic Memory Management)
- #### 重點： 
     C++ 使用 new 與 delete 運算子在 Heap (堆積) 中動態配置與釋放記憶體。若配置陣列需使用 new []，釋放時務必使用 delete [] 以防記憶體洩漏。

- #### 三大要件 (The Big Three)： 
    當類別內含有指向動態記憶體的指標時，為了避免指標被預設進行危險的「淺層複製 (Shallow Copy)」，開發者必須親自實作：(1) 解構子、(2) 複製建構子、(3) 多載指派運算子 (operator=)。
___
### 10.10 個案研究：Array 類別
- #### 重點： 
    內建的 C/C++ 陣列有很多缺點（不檢查邊界、不能直接用 = 賦值）。本節示範打造一個安全的 Array 類別。

- #### 範例： 
    多載 operator=： 實作深層複製 (Deep Copy)，確保不同物件的指標擁有各自獨立的記憶體空間。

- #### 多載 operator[]： 
    讓自訂類別能像一般陣列一樣使用方括號存取，並在內部加入邊界檢查（越界時拋出例外）。通常會提供兩個版本：一個回傳 reference (供寫入)，一個加上 const (供常數物件讀取)。
    ___
### 10.11 成員與非成員函式的比較 (Member vs. Non-Member Functions)
- #### 重點： 
    多載運算子該寫在類別內還是類別外？

- #### 選用成員函式： 
    若運算會改變左側物件的狀態（如 =, +=, ++），或者是 (), [], -> 這幾個運算子，規定必須是成員函式。

- #### 選用非成員 (全域/friend) 函式： 
    若左側運算元不是該類別的物件（如 <<、>>），或是為了讓左右兩側的運算元都享有「隱式型別轉換」的對等權利（例如 字串 + 字母 與 字母 + 字串 都能通），則應寫成非成員函式。
___
### 10.12 型別間的轉換 (Converting between Types)
- #### 重點： 
    我們可以為自訂類別定義轉換規則。

- #### 轉換建構子 (Conversion Constructor)： 
    能夠接收「單一參數」的建構子，編譯器會自動利用它將其他型別轉換為該類別的物件。

- #### 轉換運算子 (Cast Operator)： 
    可將目前的類別物件轉換成其他型別。語法為 operator 目標型別() const;（不寫回傳型態，因為函式名稱本身就是型態）。
___
### 10.13 explicit 建構子與轉換運算子
- #### 重點： 
    編譯器背後偷偷進行的「隱式型別轉換」常常會導致難以抓錯的邏輯漏洞。

- #### 範例： 
    在單一參數的建構子前面加上 explicit 關鍵字（例如 explicit Array(int size);），可以明確禁止編譯器拿這個建構子來做自動轉換。這樣一來，寫出 Array arr = 5; 就會直接跳出編譯錯誤，強迫程式設計師必須寫得更明確，提升程式安全性。
___
### 10.14 多載函式呼叫運算子 ()
- #### 重點： 
    我們可以對括號 () 進行多載。這會產生一種奇特的結果：你可以把「物件」當成「函式」一樣來呼叫。這類的物件被稱為 函式物件 (Function Object) 或 Functor。

- #### 特性： 
    operator() 必須實作為成員函式，且它可以接受任意數量的參數。

- #### 範例： 
    在 String 類別中實作 operator()(int index, int length)。在主程式中宣告了 String str; 後，就可以直接用 str(4, 2) 的奇妙語法來擷取子字串。
    ```C++
    #include <string>
    #include <iostream>
    using namespace std;

    class MyString {
    private:
    string text;
    public:
        MyString(string t) : text(t) {}

        // 多載 () 運算子，接收起始位置與長度
        string operator()(int index, int length) const {
            return text.substr(index, length);
        }    
    };

    int main() {
        MyString str("Hello C++ World");

        // 把物件 str 當成函式呼叫！
        string sub = str(6, 3); // 從索引 6 開始取 3 個字元

        cout << "擷取結果: " << sub << endl; // 輸出: C++
        return 0;
    }
    ```
    ___
    
:::info
### 範例題型&解答
:::
### ○ self-review exercises Chapter 10
#### 10.1 Fill in the blanks in each of the following:
a) When operators are overloaded as member functions, they must be ==**non-static**==, because they must be called on an object of the class and operate on that object.
b) A constructor that’s declared ==**explicit**== cannot be used in an implicit conversion.
c) Standard class string is defined in header <string> and belongs to namespace **==std==**.
d) The istream member function ==**ignore**== discards the specified number of characters in the input stream.
e) A conversion operator must be a ==**non-static**== member function.
f) You cannot change the ==**“arity”**== of an operator.
g) A constructor that can be called with a single argument can be used as a ==**conversion**== constructor.
    
#### 10.2 Explain the use of the operators new and delete.
    # ANS:
    You can control the allocation and deallocation of memory in a program for objects and for arrays of any built-in or user-defined type. This is known as dynamic memory management and is performed with the operators new and delete.
#### 10.3 In what context might an operator be used as non-member function?
    # ANS:
    If the left operand must be an object of a different class or a fundamental type, this operator function must be implemented as a non-member function. A non-member operator function can be made a friend of a class if that function must access private or protected members of that class directly.

#### 10.4 (True/False) A constructor that can be called with a single argument can be used as a conversion constructor.
    # ANS:
    True

#### 10.5 How does the “arity” of an overloaded operator compared with the “arity” of the original operator?
    # ANS:
    You cannot change the “arity” of an operator (that is, the number of operands an operator takes)-overloaded unary operators remain unary operators; overloaded binary operators remain binary operators.
___
> :copyright: written by KiHoGaoGan4570 and Sam_1268 from twitch and over 2500 black people from NigerLand