資訊之芽 week10
Header Files & Templates
By Koios
Special Thanks:readleaf23477、Jason、方淑玲
Header Files
標頭檔
標頭檔(Header Files)
- iostream
- cmath
- cstring
- ...
一些你曾經用過的 Header Files
為什麼需要標頭檔🤔
👨💻
🙆♂️
打包
引用
Header Files
- 保持程式碼的可讀性
- 保持程式碼的可維護性
- 避免程式被竄改
- 簡化工作
- 避免重複撰寫程式碼
舉個例子🌰
輸入兩個正整數 \(a\), \(b\),輸出 \(a^b\)


(先忽略 pow 存在浮點數誤差的問題)
再舉個例子🌰
輸入兩個字串 \(a\), \(b\),判斷 \(a\) 是否等同 \(b\)


不要重複造輪子
當現有的工具已經足以應付大部分的情況
就沒必要重新製造工具
(當然,在工具不堪用的情況下還是得自己造)😝
回顧大作業一
其實,在大作業一你就已經用過 Header Files
dictionary.hh
include
server.hh
GetNewWord()
Connect()
引用
try to 自製 Header Files
function.hh 包含一個函數 power(a, b) 計算 \(a^b\)
main.cc 引用 function.hh ,計算 \(a^b\)
補充:C++ 的 Header Files 常用 .hh 或 .hpp 做副檔名
自製 Header Files
記得引用要用 "",不是 <>

function.hh

main.cpp
追朔 Header Files 的內容

ctrl + 滑鼠左鍵
牛刀小試:成績統計
- https://neoj.sprout.tw/problem/226/
- 試著把 range 和 average 寫在自製的 Header Files 當中
- 在電腦上跑跑看
- 不需要上傳到 OJ
8
30 77 94 71 1 53 55 37
Max - Min = 93
Average = 52.25
Sample Input
Sample Output
#include 究竟做了什麼?
實際上,#include 就是把 #include 變成 include 的內容
🤔
舉個例子🌰

main.cpp

function.hh
舉個例子🌰

實際上就是把 #include "function.hh" 替換成 function.hh 的內容
通常我們只會將宣告內容放在 Header Files
實作細節另外處理
Why?
-
Header Files 可以很簡潔✨
-
加快編譯速度
舉個例子🌰

main.cpp
function.hh


function.cpp
同時編譯多個檔案
現在我們有 main.cpp 以及 function.cpp 需要同時編譯,該怎麼做呢?

g++ main.cpp function.cpp
Preprocessor
前置處理器
Compiler
編譯器
Linker
連接器
Assembler
組譯器
.hh/.hpp
Header File
.cc/.cpp
Program
.o
Object File
a.out
Executable File
.hh/.hpp
Header File
.cc/.cpp
Program
Preprocessor
前置處理器
Compiler
編譯器
.o
Object File
Linker
連接器
Assembler
組譯器
a.out
Executable File
🤯
只是補充,別擔心拉w
補充:Header Files 避免重複宣告
- 多個檔案使用同一個 header files
- 同時編譯造成重複宣告
- 使用巨集解決
- 透過檢查是否定義來判斷有沒有編譯過

ifndef | 檢查是否已經定義(if not define) |
---|---|
define | 定義巨集 |
endif | 結束程式塊,與 ifndef 成對 |
命名細節
- 全大寫
- 前後用兩個底線
- 將其他符號也用底線取代
補充:Header Files 避免重複宣告
- 現在多用 #pragma once 替代

macro
巨集
前置處理器 Preprocessor
- 處理指令邊譯前的預處理
- 並非 C++ 語法
- 以 # 開頭,結尾沒有分號
- Example
- #include
- #define
- #ifdef
- #pragma
#define - 創造常數(巨集)
#define [想取代的字串] [用來取代的內容]

#define - 包含參數的巨集
#define [想取代的字串](參數) [用來取代的內容]

它真的只是取代而已🤪
舉個例子🌰

輸入 3 7 會輸出 100 ?
真的真的只是取代而已


=
牛刀小試:三個數字最大值
輸入三個數字 \(a\) \(b\) \(c\),嘗試用巨集定義一個函數判斷三個數字的最大值
5 3 10
10
Sample Input
Sample Output
namespace
命名空間
還記得 using namespace std 嗎
所以 namespace 到底是什麼🤔
想像現在資芽小學校當中有很多班級
不過是兩個不同的 Bob
那麼,在資芽小學校找 Bob 的時候,到底是找哪個 Bob 呢?
🙋♂️
在2022班有個 Bob
🙋
在2021班也有個 Bob
🙋♂️
🙋
在2022班有個 Bob
在2021班也有個 Bob
如果你要找 2022 班的 Bob,那應該就要說
"我想要找 2022 班的 Bob"
想像現在資芽小學校當中有很多班級



C2022 班的 Bob
C2022::Bob
namespace
- 避免撞名
- 可以放變數、struct、函數、namespace、...
- 透過 using namespace 簡化省略 namespace 名稱
- e.g. std::cin => cin
Templates
模板
假設今天芽芽要你設計一個比較數字大小的 Function
一塊小 🍰!

再假設芽芽又說你的函數要支援比較 double
哼!又一塊小 🍰!
我還不複製貼上!

Ctrl-C + Ctrl-V !
再假設芽芽又說你的函數要支援比較
long long, unsigned int, etc...
於是你就
Ctrl-C + Ctrl-V
Ctrl-C + Ctrl-V
Ctrl-C + Ctrl-V
Ctrl-C + Ctrl-V
Ctrl-C + Ctrl-V
複製貼上錯了嗎 😢
-
整份程式碼落落長 🧐
-
Debug 時要 De 很久 🐛
-
複製幾次就要改幾次 🤯
那該怎麼辦ㄋ🤔
大家一起來想想看吧
既然變動的地方只有型別
那就只要把型別當成變數就可以了!
🤯
參數多型
-
一個可以把型別參數化的酷東東
-
C++ 透過 template 實現
舉個例子🌰

回傳型別也可以參數化

甚至可以多個型別參數

牛刀小試:交換兩變數
試著透過 template 實作 Swapp 函數
同時支援 int、long long、double、char 的交換
References
-
https://drive.google.com/file/d/1sAUNCd79RDE23to8osthJQiw5zPAxPOP/view
-
https://docs.google.com/presentation/d/11RWKEOWb-Efgw8FUhyFDn8p9VkvEj-C3vgbuzST3QLw/edit#slide=id.p
-
https://tw-csie-sprout.github.io/c2021/slides/template/#/
-
https://blog.csdn.net/SummerXRT/article/details/119741741
-
https://www.runoob.com/cplusplus/cpp-preprocessor.html
-
https://hackmd.io/@sysprog/c-prog/%2Fs%2FS1maxCXMl
-
https://blog.gtwang.org/programming/howto-create-library-using-gcc/
-
https://viml.nchc.org.tw/archive_blog_340/
-
https://jasonblog.github.io/note/c++/shi_fou_neng_rang_c_++_template_de_biao_tou_dang_z.html
-
https://www.796t.com/content/1546810237.html
-
https://www.runoob.com/cplusplus/cpp-namespaces.html
-
https://docs.microsoft.com/zh-tw/cpp/cpp/namespaces-cpp?view=msvc-170
-
https://www.cplusplus.com/doc/tutorial/namespaces/
資訊之芽 week10 Header Files & Templates
By koios
資訊之芽 week10 Header Files & Templates
- 266