# 🧩 範型(Template) --- - **學習目標:** - 了解 C++ 範型(Template)的概念 - 學會使用函式樣板與類別樣板 - 瞭解範型的好處與使用情境 --- ## 🔖 什麼是範型? - **範型(Template)** 是 C++ 提供的一種泛型程式設計機制 - 允許函式或類別能夠處理多種資料型態,而不必重複撰寫程式碼 - 主要分為兩類: 1. **函式樣板(Function Template)** 2. **類別樣板(Class Template)** --- ## 📌 沒有範型時的問題 ```cpp int maxInt(int a, int b) { return (a > b) ? a : b; } double maxDouble(double a, double b) { return (a > b) ? a : b; } ``` - 雖然功能一樣,但必須為不同型別重複撰寫程式碼 → 程式碼冗長 --- ## 🚩 函式樣板(Function Template) ```cpp template <typename T> T myMax(T a, T b) { return (a > b) ? a : b; } ``` ---- ### 使用方式 ```cpp cout << myMax(3, 5) << endl; // int cout << myMax(3.2, 2.5) << endl; // double cout << myMax('A', 'Z') << endl; // char ``` --- - 多型(Polymorphism):在執行期決定行為(透過虛擬函式) - 範型(Template):在編譯期決定型態(編譯器會為不同型別產生對應版本) --- ## 🚩 多參數樣板 ```cpp template <typename T1, typename T2> void printPair(T1 a, T2 b) { cout << a << " - " << b << endl; } int main() { printPair(10, 3.14); // int, double printPair("Age", 25); // const char*, int } ``` --- ## 📌 類別樣板(Class Template) ```cpp template <typename T> class Box { private: T value; public: Box(T v) : value(v) {} void show() { cout << value << endl; } }; ``` ---- ### 使用方式: ```cpp Box<int> b1(123); Box<string> b2("Hello"); b1.show(); // 123 b2.show(); // Hello ``` --- ## 🚩 類別樣板與多個型態參數 ```cpp template <typename T1, typename T2> class Pair { private: T1 first; T2 second; public: Pair(T1 f, T2 s) : first(f), second(s) {} void show() { cout << first << ", " << second << endl; } }; Pair<string, int> p("Age", 20); p.show(); // Age, 20 ``` --- ### 📗 範型與預設參數 ```cpp template <typename T = int> class Number { private: T value; public: Number(T v) : value(v) {} void show() { cout << value << endl; } }; Number<> n1(10); // 預設型態 int Number<double> n2(3.14); ``` ---- ### 🚩 範例:泛型 Stack 類別 ```cpp template <typename T> class Stack { private: vector<T> data; public: void push(T value) { data.push_back(value); } void pop() { data.pop_back(); } T top() { return data.back(); } bool empty() { return data.empty(); } }; Stack<int> s; s.push(10); s.push(20); cout << s.top(); // 20 ``` --- ## ⚠️ 範型注意事項 - 範型會在編譯期產生對應型態的程式碼 - 若型態不支援使用的運算子,會導致編譯錯誤 - 範型定義必須與實作放在同一個 .h 檔案(否則可能連結錯誤) --- ## 🛠️ 課堂練習 (Lab) - 練習一 - 撰寫一個 swapValues 函式樣板,能交換任意型態的兩個變數。 - 練習二 - 實作一個 Stack 類別樣板。 Note: ```cpp #pragma once #include <vector> #include <stdexcept> #include <utility> #include <cstddef> template <typename T> class Stack { public: using value_type = T; using size_type = std::size_t; using reference = value_type&; using const_reference = const value_type&; Stack() = default; template <class It> Stack(It first, It last) : data_(first, last) {} bool empty() const { return data_.empty(); } size_type size() const { return data_.size(); } void clear() { data_.clear(); } // push:同時支援 lvalue / rvalue void push(const T& v) { data_.push_back(v); } void push(value_type&& v) { data_.push_back(std::move(v)); } // 就地建構,回傳頂端元素參考以便鏈式使用 template <class... Args> reference emplace(Args&&... args) { data_.emplace_back(std::forward<Args>(args)...); return data_.back(); } // 取頂端;空堆疊時丟出例外 T& top() { if (empty()) throw std::out_of_range("Stack::top on empty stack"); return data_.back(); } const T& top() const { if (empty()) throw std::out_of_range("Stack::top on empty stack"); return data_.back(); } // 彈出;空堆疊時丟出例外 void pop() { if (empty()) throw std::out_of_range("Stack::pop on empty stack"); data_.pop_back(); } // 強例外安全的 swap void swap(Stack& other) noexcept(noexcept(data_.swap(other.data_))) { data_.swap(other.data_); } private: std::vector<T> data_; }; ``` ```cpp // main.cpp #include <iostream> #include <memory> #include "stack.hpp" using std::cout; int main() { Stack<int> s; s.push(10); s.push(20); s.emplace(30); cout << "size=" << s.size() << ", top=" << s.top() << "\n"; // size=3, top=30 s.pop(); cout << "top=" << s.top() << "\n"; // 20 // 字串 Stack<std::string> ss; ss.emplace("hello"); ss.push(std::string("world")); cout << ss.top() << "\n"; // world // 支援移動語意(move-only) Stack<std::unique_ptr<int>> su; su.push(std::make_unique<int>(42)); cout << *su.top() << "\n"; // 42 // 建構於迭代器區間 int a[]{1,2,3,4}; Stack<int> s2(std::begin(a), std::end(a)); cout << "s2.top=" << s2.top() << ", size=" << s2.size() << "\n"; // 4, 4 } ``` --- ## 💡 本週作業 - 實作一個 MathTool 類別樣板,提供 add, subtract, multiply, divide 四個泛型函式。
{"title":"🧩 第八週:範型(Template)","breaks":true,"description":"學習目標:","contributors":"[{\"id\":\"01487228-6720-47a9-875f-2f01b5d455ad\",\"add\":4773,\"del\":2436,\"latestUpdatedAt\":1755586815163}]"}
    80 views