Skip to content

C++ 模板

模板是 C++ 中实现泛型编程的重要特性,它允许编写与类型无关的代码。模板可以分为函数模板和类模板。

1. 模板的基本概念

模板是一种参数化的类型或函数,它允许在编译时根据实际使用的类型生成相应的代码。

1.1 函数模板

cpp
#include <iostream>

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << "10 + 20 = " << add(10, 20) << std::endl;
    std::cout << "10.5 + 20.5 = " << add(10.5, 20.5) << std::endl;
    
    return 0;
}

1.2 类模板

cpp
#include <iostream>

template <typename T>
class Stack {
private:
    T* data;
    int top;
    int capacity;

public:
    Stack(int size) : capacity(size), top(-1) {
        data = new T[capacity];
    }
    
    ~Stack() {
        delete[] data;
    }
    
    void push(T value) {
        if (top == capacity - 1) {
            std::cout << "栈已满" << std::endl;
            return;
        }
        data[++top] = value;
    }
    
    T pop() {
        if (top == -1) {
            std::cout << "栈为空" << std::endl;
            return T();
        }
        return data[top--];
    }
    
    bool is_empty() {
        return top == -1;
    }
};

int main() {
    Stack<int> int_stack(5);
    int_stack.push(10);
    int_stack.push(20);
    int_stack.push(30);
    
    while (!int_stack.is_empty()) {
        std::cout << int_stack.pop() << " ";
    }
    std::cout << std::endl;
    
    Stack<double> double_stack(5);
    double_stack.push(10.5);
    double_stack.push(20.5);
    double_stack.push(30.5);
    
    while (!double_stack.is_empty()) {
        std::cout << double_stack.pop() << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

2. 函数模板

2.1 基本用法

cpp
#include <iostream>

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    std::cout << "max(10, 20) = " << max(10, 20) << std::endl;
    std::cout << "max(10.5, 20.5) = " << max(10.5, 20.5) << std::endl;
    
    return 0;
}

2.2 多个模板参数

cpp
#include <iostream>

template <typename T, typename U>
void print(T a, U b) {
    std::cout << "a = " << a << ", b = " << b << std::endl;
}

int main() {
    print(10, 20);
    print(10, 20.5);
    print(10.5, 20);
    print(10.5, 20.5);
    
    return 0;
}

2.3 模板特化

cpp
#include <iostream>

template <typename T>
T max(T a, T b) {
    std::cout << "通用模板" << std::endl;
    return (a > b) ? a : b;
}

template <>
int max<int>(int a, int b) {
    std::cout << "int 特化" << std::endl;
    return (a > b) ? a : b;
}

int main() {
    std::cout << "max(10, 20) = " << max(10, 20) << std::endl;
    std::cout << "max(10.5, 20.5) = " << max(10.5, 20.5) << std::endl;
    
    return 0;
}

3. 类模板

3.1 基本用法

cpp
#include <iostream>

template <typename T>
class Box {
private:
    T value;

public:
    Box(T value) : value(value) {}
    
    T get_value() {
        return value;
    }
    
    void set_value(T value) {
        this->value = value;
    }
};

int main() {
    Box<int> int_box(10);
    std::cout << "int_box.get_value() = " << int_box.get_value() << std::endl;
    
    Box<double> double_box(10.5);
    std::cout << "double_box.get_value() = " << double_box.get_value() << std::endl;
    
    return 0;
}

3.2 多个模板参数

cpp
#include <iostream>

template <typename T, typename U>
class Pair {
private:
    T first;
    U second;

public:
    Pair(T first, U second) : first(first), second(second) {}
    
    T get_first() {
        return first;
    }
    
    U get_second() {
        return second;
    }
    
    void print() {
        std::cout << "first = " << first << ", second = " << second << std::endl;
    }
};

int main() {
    Pair<int, double> pair1(10, 20.5);
    pair1.print();
    
    Pair<std::string, int> pair2("Hello", 20);
    pair2.print();
    
    return 0;
}

3.3 模板特化

cpp
#include <iostream>

template <typename T>
class Box {
private:
    T value;

public:
    Box(T value) : value(value) {}
    
    void print() {
        std::cout << "通用模板: value = " << value << std::endl;
    }
};

template <>
class Box<int> {
private:
    int value;

public:
    Box(int value) : value(value) {}
    
    void print() {
        std::cout << "int 特化: value = " << value << std::endl;
    }
};

int main() {
    Box<int> int_box(10);
    int_box.print();
    
    Box<double> double_box(10.5);
    double_box.print();
    
    return 0;
}

4. 非类型模板参数

非类型模板参数是指在模板参数中使用常量表达式。

cpp
#include <iostream>

template <typename T, int size>
class Array {
private:
    T data[size];

public:
    T& operator[](int index) {
        return data[index];
    }
    
    int get_size() {
        return size;
    }
};

int main() {
    Array<int, 5> arr;
    
    for (int i = 0; i < arr.get_size(); i++) {
        arr[i] = i * 10;
    }
    
    for (int i = 0; i < arr.get_size(); i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

5. 模板和友元

cpp
#include <iostream>

template <typename T>
class Box;

template <typename T>
void print_box(Box<T>& box);

template <typename T>
class Box {
private:
    T value;
    
    friend void print_box<T>(Box<T>& box);

public:
    Box(T value) : value(value) {}
};

template <typename T>
void print_box(Box<T>& box) {
    std::cout << "value = " << box.value << std::endl;
}

int main() {
    Box<int> int_box(10);
    print_box(int_box);
    
    Box<double> double_box(10.5);
    print_box(double_box);
    
    return 0;
}

6. 模板和静态成员

cpp
#include <iostream>

template <typename T>
class Counter {
private:
    static int count;

public:
    Counter() {
        count++;
    }
    
    ~Counter() {
        count--;
    }
    
    static int get_count() {
        return count;
    }
};

template <typename T>
int Counter<T>::count = 0;

int main() {
    Counter<int> int_counter1;
    Counter<int> int_counter2;
    std::cout << "int_counter count = " << Counter<int>::get_count() << std::endl;
    
    Counter<double> double_counter1;
    Counter<double> double_counter2;
    Counter<double> double_counter3;
    std::cout << "double_counter count = " << Counter<double>::get_count() << std::endl;
    
    return 0;
}

7. 示例:综合运用

现在,让我们看一个综合运用各种模板特性的例子:

cpp
#include <iostream>
#include <string>

template <typename T>
class Stack {
private:
    T* data;
    int top;
    int capacity;

public:
    Stack(int size) : capacity(size), top(-1) {
        data = new T[capacity];
    }
    
    ~Stack() {
        delete[] data;
    }
    
    void push(T value) {
        if (top == capacity - 1) {
            std::cout << "栈已满" << std::endl;
            return;
        }
        data[++top] = value;
    }
    
    T pop() {
        if (top == -1) {
            std::cout << "栈为空" << std::endl;
            return T();
        }
        return data[top--];
    }
    
    T peek() {
        if (top == -1) {
            std::cout << "栈为空" << std::endl;
            return T();
        }
        return data[top];
    }
    
    bool is_empty() {
        return top == -1;
    }
    
    bool is_full() {
        return top == capacity - 1;
    }
    
    int get_size() {
        return top + 1;
    }
};

template <typename T, typename U>
class Pair {
private:
    T first;
    U second;

public:
    Pair(T first, U second) : first(first), second(second) {}
    
    T get_first() {
        return first;
    }
    
    U get_second() {
        return second;
    }
    
    void print() {
        std::cout << "first = " << first << ", second = " << second << std::endl;
    }
};

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

template <typename T>
T min(T a, T b) {
    return (a < b) ? a : b;
}

int main() {
    // 测试 Stack
    std::cout << "测试 Stack:" << std::endl;
    Stack<int> int_stack(5);
    int_stack.push(10);
    int_stack.push(20);
    int_stack.push(30);
    
    std::cout << "栈顶元素: " << int_stack.peek() << std::endl;
    std::cout << "栈的大小: " << int_stack.get_size() << std::endl;
    
    while (!int_stack.is_empty()) {
        std::cout << int_stack.pop() << " ";
    }
    std::cout << std::endl;
    std::cout << std::endl;
    
    // 测试 Pair
    std::cout << "测试 Pair:" << std::endl;
    Pair<int, double> pair1(10, 20.5);
    pair1.print();
    
    Pair<std::string, int> pair2("Hello", 20);
    pair2.print();
    std::cout << std::endl;
    
    // 测试 max 和 min
    std::cout << "测试 max 和 min:" << std::endl;
    std::cout << "max(10, 20) = " << max(10, 20) << std::endl;
    std::cout << "min(10, 20) = " << min(10, 20) << std::endl;
    std::cout << "max(10.5, 20.5) = " << max(10.5, 20.5) << std::endl;
    std::cout << "min(10.5, 20.5) = " << min(10.5, 20.5) << std::endl;
    
    return 0;
}

小结

C++ 模板包括:

  1. 模板的基本概念

    • 模板是一种参数化的类型或函数
    • 用于实现泛型编程
  2. 函数模板

    • 基本用法:template <typename T> T func(T a, T b) { ... }
    • 多个模板参数:template <typename T, typename U> void func(T a, U b) { ... }
    • 模板特化:为特定类型提供特殊实现
  3. 类模板

    • 基本用法:template <typename T> class ClassName { ... };
    • 多个模板参数:template <typename T, typename U> class ClassName { ... };
    • 模板特化:为特定类型提供特殊实现
  4. 非类型模板参数

    • 在模板参数中使用常量表达式
  5. 模板和友元

    • 模板类可以有友元函数
  6. 模板和静态成员

    • 模板类的静态成员对于每种类型都是独立的

关键概念:

  • 模板:一种参数化的类型或函数
  • 函数模板:参数化的函数
  • 类模板:参数化的类
  • 模板特化:为特定类型提供特殊实现
  • 非类型模板参数:在模板参数中使用常量表达式
  • 泛型编程:编写与类型无关的代码

掌握模板是编写通用 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的预处理器。