S SmartDocs
Chuỗi bài: C++ cpp 206 dòng · Cập nhật 2026-04-03

class_templates.cpp

C++/Part3_泛型與STL/Ch12_模板程式設計/class_templates.cpp

// class_templates.cpp
// 類別模板:Stack 與 Pair 的完整實作示範
// 編譯:g++ -std=c++17 -Wall -o class_templates class_templates.cpp

#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>

// ============================================================
// 1. 類別模板 Stack<T>
//    使用 std::vector 作為底層容器
// ============================================================
template <typename T>
class Stack {
    std::vector<T> data_;

public:
    void push(const T& value);
    void pop();
    const T& top() const;
    bool empty() const { return data_.empty(); }
    std::size_t size() const { return data_.size(); }
    void print() const;
};

// 成員函式定義在類別外——每個都需要 template <typename T> 前綴
template <typename T>
void Stack<T>::push(const T& value) {
    data_.push_back(value);
}

template <typename T>
void Stack<T>::pop() {
    if (data_.empty()) {
        throw std::out_of_range("Stack<T>::pop(): 堆疊為空");
    }
    data_.pop_back();
}

template <typename T>
const T& Stack<T>::top() const {
    if (data_.empty()) {
        throw std::out_of_range("Stack<T>::top(): 堆疊為空");
    }
    return data_.back();
}

template <typename T>
void Stack<T>::print() const {
    std::cout << "Stack [底 -> 頂]: ";
    for (const auto& item : data_) {
        std::cout << item << " ";
    }
    std::cout << "(大小: " << data_.size() << ")" << std::endl;
}

// ============================================================
// 2. 類別模板 Pair<T, U> — 儲存兩個不同型別的值
// ============================================================
template <typename T, typename U>
class Pair {
    T first_;
    U second_;

public:
    Pair(const T& f, const U& s) : first_(f), second_(s) {}

    const T& first() const { return first_; }
    const U& second() const { return second_; }

    void print() const {
        std::cout << "(" << first_ << ", " << second_ << ")";
    }
};

// ============================================================
// 3. 帶預設型別參數的類別模板
// ============================================================
template <typename T = int, typename Container = std::vector<T>>
class SimpleList {
    Container data_;

public:
    void add(const T& value) { data_.push_back(value); }

    void print(const std::string& label) const {
        std::cout << label << ": [";
        for (std::size_t i = 0; i < data_.size(); ++i) {
            if (i > 0) std::cout << ", ";
            std::cout << data_[i];
        }
        std::cout << "]" << std::endl;
    }

    std::size_t size() const { return data_.size(); }
};

// ============================================================
// 主程式
// ============================================================
int main() {
    std::cout << "========================================" << std::endl;
    std::cout << "  類別模板(Class Templates)示範" << std::endl;
    std::cout << "========================================\n" << std::endl;

    // --- 1. Stack<int> ---
    std::cout << "--- 1. Stack<int> ---" << std::endl;

    Stack<int> int_stack;
    int_stack.push(10);
    int_stack.push(20);
    int_stack.push(30);
    int_stack.print();

    std::cout << "頂端元素: " << int_stack.top() << std::endl;
    int_stack.pop();
    std::cout << "pop 後: ";
    int_stack.print();

    std::cout << std::endl;

    // --- 2. Stack<std::string> ---
    std::cout << "--- 2. Stack<std::string> ---" << std::endl;

    Stack<std::string> str_stack;
    str_stack.push("Hello");
    str_stack.push("Template");
    str_stack.push("World");
    str_stack.print();

    std::cout << "頂端元素: " << str_stack.top() << std::endl;
    str_stack.pop();
    str_stack.pop();
    std::cout << "pop 兩次後: ";
    str_stack.print();

    std::cout << std::endl;

    // --- 3. 空堆疊例外處理 ---
    std::cout << "--- 3. 空堆疊例外處理 ---" << std::endl;

    Stack<double> empty_stack;
    try {
        empty_stack.top();
    } catch (const std::out_of_range& e) {
        std::cout << "捕獲例外: " << e.what() << std::endl;
    }

    try {
        empty_stack.pop();
    } catch (const std::out_of_range& e) {
        std::cout << "捕獲例外: " << e.what() << std::endl;
    }

    std::cout << std::endl;

    // --- 4. Pair<T, U> ---
    std::cout << "--- 4. Pair<T, U> ---" << std::endl;

    Pair<std::string, int> student("Alice", 95);
    std::cout << "學生: ";
    student.print();
    std::cout << std::endl;
    std::cout << "  姓名: " << student.first() << std::endl;
    std::cout << "  成績: " << student.second() << std::endl;

    Pair<int, double> coord(3, 4.5);
    std::cout << "座標: ";
    coord.print();
    std::cout << std::endl;

    Pair<std::string, std::string> kv("language", "C++");
    std::cout << "鍵值對: ";
    kv.print();
    std::cout << std::endl;

    std::cout << std::endl;

    // --- 5. 預設型別參數 ---
    std::cout << "--- 5. 預設型別參數 SimpleList ---" << std::endl;

    SimpleList<> default_list;  // T = int, Container = vector<int>
    default_list.add(1);
    default_list.add(2);
    default_list.add(3);
    default_list.print("預設 (int)");

    SimpleList<double> double_list;  // T = double, Container = vector<double>
    double_list.add(1.1);
    double_list.add(2.2);
    double_list.add(3.3);
    double_list.print("double 版本");

    SimpleList<std::string> string_list;
    string_list.add("C++");
    string_list.add("Java");
    string_list.add("Python");
    string_list.print("string 版本");

    std::cout << "\n========================================" << std::endl;
    std::cout << "  類別模板示範結束" << std::endl;
    std::cout << "========================================" << std::endl;

    return 0;
}

Bài viết liên quan