## 🔄 第五週:運算子多載(Operator Overloading)
---
- **學習目標:**
- 認識運算子多載的用途
- 學會實作常見運算子的多載
- 提升物件的使用直覺性與便利性
---
## 🔖 什麼是運算子多載?
- **Operator Overloading**
定義類別運算子的行為,使物件能直接使用各種運算子(如 `+`, `-`, `<<` 等)。
- 提升程式碼可讀性,讓物件用起來像內建型別一樣自然。
----
```cpp
Complex a(1,2), b(3,4);
Complex c = a + b; // 運算子多載後即可直接使用+
```
---
## 📌 運算子多載的語法規則
```cpp
return_type operator symbol(parameters){
// ...
}
```
- 可以用 `成員函式` 或 `非成員函式` 實作。
Note:
- 非成員函式
- 非成員函式是獨立於任何類別的函式,它不屬於任何物件(object),通常是定義在類別外的函式。
```cpp
#include <iostream>
#include <cmath>
using namespace std;
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
};
// 非成員函式
double distance(const Point& a, const Point& b) {
int dx = a.x - b.x;
int dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
int main() {
Point p1(1, 2), p2(4, 6);
cout << distance(p1, p2) << endl;
return 0;
}
```
----
## 🚩 範例:複數
```cpp
class Complex {
private:
int real, imag;
public:
Complex(int r, int i) : real(r), imag(i) {}
// 使用成員函式多載 +
Complex operator+(const Complex &c) {
return Complex(real + c.real, imag + c.imag);
}
void show() {
cout << real << "+" << imag << "i" << endl;
}
};
```
----
### 使用方式:
```cpp
Complex c1(1,2), c2(3,4);
Complex c3 = c1 + c2; // 使用 + 運算子
c3.show(); // 4+6i
```
---
### 📗 非成員函式實作多載
- 運算子多載也可使用非成員函式(常與 `friend` 一起使用)
```cpp
class Complex {
private:
int real, imag;
public:
Complex(int r, int i) : real(r), imag(i) {}
void show() const {
cout << real << "+" << imag << "i" << endl;
}
// friend 函式:Complex + Complex
friend Complex operator+(const Complex &a, const Complex &b);
// friend 函式:Complex + int
friend Complex operator+(const Complex &a, int b);
// friend 函式:int + Complex
friend Complex operator+(int a, const Complex &b);
};
// Complex + Complex
Complex operator+(const Complex &a, const Complex &b) {
return Complex(a.real + b.real, a.imag + b.imag);
}
// Complex + int
Complex operator+(const Complex &a, int b) {
return Complex(a.real + b, a.imag);
}
// int + Complex
Complex operator+(int a, const Complex &b) {
return Complex(a + b.real, b.imag);
}
```
----
### 使用
```cpp
#include <iostream>
using namespace std;
int main() {
Complex c1(3, 4), c2(1, 2);
Complex result1 = c1 + c2; // Complex + Complex
Complex result2 = c1 + 5; // Complex + int
Complex result3 = 5 + c1; // int + Complex
result1.show(); // 4+6i
result2.show(); // 8+4i
result3.show(); // 8+4i
return 0;
}
```
----
## 非成員式多載 使用時機
- [為什麼在 C++ 中使用 Non-member Function(非成員函式)](/meu_hsEFQFKPRTkrz4zZ-g)
---
## 🚩 多載輸出運算子 <<
- 常用來輸出物件內容
```cpp
#include <iostream>
using namespace std;
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
friend ostream& operator<<(ostream &out, const Point &p);
};
ostream& operator<<(ostream &out, const Point &p) {
out << "(" << p.x << ", " << p.y << ")";
return out;
}
```
----
### 使用方式:
```cpp
Point p(3, 4);
cout << p; // (3, 4)
```
----
## 練習
- 把 `Complex` 加入 `<<` 輸出運算子 `friend`
Note:
```cpp
friend ostream& operator<<(ostream& os, const Complex& c);
ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
cout << "c = " << c << endl;
```
---
## 📗 多載比較運算子 (==, <, >)
```cpp
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
bool operator==(const Point &p) {
return (x == p.x && y == p.y);
}
};
```
----
### 使用方式:
```cpp
Point p1(3,4), p2(3,4);
if(p1 == p2)
cout << "相同座標!";
```
---
## 📗 運算子多載注意事項
- 不可任意改變運算子原本的意義(如 + 做成減法)
- 有些運算子不可多載(如., ::, ?:, .*)
- 保持直覺且簡單
---
## 🚩 常用的多載運算子整理
| 運算子 | 說明 | 常見用途 |
| --------- | ---------- | ------------------- |
| + - * / | 四則運算 | 向量、矩陣、複數 |
| << >> | 輸入輸出 | cout 輸出、cin 輸入 |
| << >> | 輸入輸出 | cout 輸出、cin 輸入 |
| == != < > | 比較運算子 | 物件間比較 |
| [] | 存取元素 | 陣列、字串、容器 |
| = | 賦值運算子 | 物件複製與初始化 |
---
## 🛠️ 課堂練習 (Lab)
- 練習一:
- 設計 Vector3D 類別(向量),並多載 + 、 * 及 << 運算子。
- 練習二:
- 建立一個分數類別 Fraction,多載 +, -, 及 == 運算子。
Note:
```cpp
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class Vector3d{
private:
int x;
int y;
int z;
public:
Vector3d(int x, int y, int z ):x(x),y(y),z(z){}
// this + a
Vector3d operator+(const Vector3d &a){
return Vector3d(x+a.x , y+a.y , z+a.z);
}
// vector3d * int
// int * vector3d
friend Vector3d operator*(const Vector3d&a, int b);
friend Vector3d operator*(int a, const Vector3d& b);
friend ostream& operator<<(ostream &out, const Vector3d&a);
};
Vector3d operator*(const Vector3d&a, int b){
return Vector3d( a.x*b ,a.y*b , a.z*b);
}
Vector3d operator*(int a, const Vector3d& b){
return Vector3d( a*b.x , a*b.y , a*b.z);
}
ostream& operator<<(ostream &out, const Vector3d&a){
out << a.x << " "<< a.y << " "<< a.z << endl;
return out;
}
int main() {
Vector3d a(1, 2, 3);
Vector3d b(4, 5, 6);
Vector3d c = 3 * b; // 使用 + 運算子
Vector3d c1 = b * 3; // 使用 + 運算子
ofstream fout("output.txt");
fout << c;
return 0;
}
```
---
## 💡 本週作業
- 設計一個 String 類別,支援串接(+)與相等(==)運算子。
{"title":"🔄 運算子多載(Operator Overloading)","description":"學習目標:","contributors":"[{\"id\":\"01487228-6720-47a9-875f-2f01b5d455ad\",\"add\":6594,\"del\":1173,\"latestUpdatedAt\":1753861761013}]"}