---
# System prepended metadata

title: Advanced function
tags: [' note', books]

---

---
tags: books, note
---


# Advanced function

## Function overload
:::info
又稱函式多載、函式重載、函式超載
:::

即使是用同樣的函數名稱，有的時候會呼叫到的是不同的函式

e.g.

```cpp=
float f = 1.5;
auto result = round(f);
cout << typeid(decltype(result)).name() << endl;
```
```result: f```
```cpp=
double f = 1.5;
auto result = round(f);
cout << typeid(decltype(result)).name() << endl;
```
```result: d```
```cpp=
long double f = 1.5;
auto result = round(f);
cout << typeid(decltype(result)).name() << endl;
```
```result: e```

由上述例子我們可以知道即使是同一個函式名稱，內建函式round還是有至少三種版本
1. ```float round(float value);```
2. ```double round(double value);```
3. ```long double round(long double value);```

那要多載一個函數也很簡單，只要確定函數的參數不一樣就可以讓多個版本同時存在

```cpp=
int add(int a, int b) {
	return a + b;
}
int add(int* a, int* b) {
	return *a + *b;
}
int main() {
	int a = 3, b = 5;
	cout << "add(int, int)   " << add(a, b) << endl;
	cout << "add(int*, int*) " << add(&a, &b) << endl;
	return 0;
}
```
```
add(int, int)   8
add(int*, int*) 8
```

除了參數型態不一樣，參數數量不一樣也可以

```cpp=
int add(int a, int b) {
	return a + b;
}
int add(int a, int b, int c) {
	return a + b + c;
}

int main() {
	int a = 3, b = 5, c = 7;
	cout << "add(int, int)      " << add(a, b) << endl;
	cout << "add(int, int, int) " << add(a, b, c) << endl;
	return 0;
}
```

```
add(int, int)      8
add(int, int, int) 15
```

---

## Operator overload
:::info
又稱運算子多載、運算子重載
:::

在開始前我們先來了解一下運算子的呼叫方式
像如果要做一個字串串接，我們應該會用這種形式

e.g.
```cpp=
string a = "123", b = "456";
cout << a + b << endl;
```
```result: 123456```

那其實我們也可以用類似函式呼叫的方式來進行

e.g.
```cpp=
cout << operator+(a, b) << endl;
```

```result: 123456```

除了一般的函式可以多載外，運算子某種意義來說也算是函式的一種
所以**運算子大部分都可以多載**

:::info
這裡舉出一些不能被多載的運算子
```::``` 範疇解析運算子
```.```  成員存取運算子
```dynamic_cast``` 執行時檢查類型轉換運算子(?)
```static_cast``` 未經檢查的類型轉換運算子(?)
```reinterpret_cast```重定義類型轉換運算子(?)
```const_cast``` 更改非常數屬性運算子(?)
```typeid```取得類型資訊運算子(?)
```sizeof```取大小運算子(?)
```.*```	成員物件選擇運算子(?)
```c?t:f```三元條件運算子
```throw```丟擲異常運算子
:::

多載的方法就跟函式多載基本上一樣，不過你不能覆蓋已經存在的運算子

:::warning
e.g.
```cpp=
int operator+(int a, int b){
    return a + b + 10;
}
```
因為`int`跟`int`的加法運算已經被定義過了，所以就會編譯錯誤
:::

:::danger
error: 'int operator+(int, int)' must have an argument of class or enumerated type
:::

因此需要有至少一個引數是自訂`class`或`enum`

```cpp=
struct itype {int x;};
itype operator+(itype a, itype b) {
	return {a.x + b.x + 10};
}
int main() {
	cout << (itype{5} + itype{6}).x << endl;
	return 0;
}
```
```result: 21```

因為幾乎每個運算子都有固定的引數數量，所以多載的時候要注意引數有幾個

:::warning
e.g.
```cpp=
struct itype {int x;};
itype operator+(itype a, itype b, itype c) {
	return {a.x + b.x + c.x + 10};
}
```
:::

:::danger
error: 'itype operator+(itype, itype, itype)' must take either one or two arguments
:::

### 習慣用法

可以透過多載`operator<`來讓自訂類別可以`sort`

```cpp=
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct two_element {
	int first, second;
};
bool operator<(two_element a, two_element b) {
	if (a.first != b.first)
		return a.first > b.first;
	else
		return a.second > b.second;
}
int main() {
	vector<two_element> v{{2, 2}, {3, 1}, {2, 1}};
	sort(v.begin(), v.end());
	for (const auto& i : v)
		cout << i.first << ' ' << i.second << endl;
	return 0;
}
```

```
result:
3 1
2 2
2 1
```

---

## Default Arguments
:::info
又稱預設參數、預設引數
:::

如果今天有個函數```add```
需要進行兩個數的加法或三個數的加法
那我們可以用上面學過的 [Function overload](#Function-overload)來實現

i.e.
```cpp=
int add(int a, int b){
    return a + b;
}
int add(int a, int b, int c){
    return a + b + c;
}
```

但是這樣類似的東西就寫了兩次，既慢又不好看
那接下來就要介紹其中一個解決辦法: Default Arguments

正如名字裡敘述的，這個解決辦法就是將引數設預設值
講明白一點就是讓不指定引數值時，有一個預設的值可以用
剛剛那個例子就可以這樣改

i.e.
```cpp=
int add(int a, int b, int c = 0) {
	return a + b + c;
}
```

在第三個引數`c`沒有用到時讓它預設為 $0$
就可以達到跟上面多載兩個`add`一樣的效果


另外，Default Arguments 使用上需要注意的地方

e.g.
```cpp=
int add(int a, int b = 0, int c) {
	return a + b + c;
}
```

:::danger
error: default argument missing for parameter 3 of 'int add(int, int, int)'
:::

像是這樣，中間有預設引數但後面沒有就會導致編譯錯誤
所以要將第一個用 Default Arguments 後的所有引數都設 Defalut argement才合法

e.g.
```cpp=
int add(int a, int b = 0, int c = 0) {
	return a + b + c;
}
```


> [color=#4ee0b9][name=9th進階教學$] [time=Sat, May 16, 2020 11:56 AM]