Appearance
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++ 模板包括:
模板的基本概念:
- 模板是一种参数化的类型或函数
- 用于实现泛型编程
函数模板:
- 基本用法:
template <typename T> T func(T a, T b) { ... } - 多个模板参数:
template <typename T, typename U> void func(T a, U b) { ... } - 模板特化:为特定类型提供特殊实现
- 基本用法:
类模板:
- 基本用法:
template <typename T> class ClassName { ... }; - 多个模板参数:
template <typename T, typename U> class ClassName { ... }; - 模板特化:为特定类型提供特殊实现
- 基本用法:
非类型模板参数:
- 在模板参数中使用常量表达式
模板和友元:
- 模板类可以有友元函数
模板和静态成员:
- 模板类的静态成员对于每种类型都是独立的
关键概念:
- 模板:一种参数化的类型或函数
- 函数模板:参数化的函数
- 类模板:参数化的类
- 模板特化:为特定类型提供特殊实现
- 非类型模板参数:在模板参数中使用常量表达式
- 泛型编程:编写与类型无关的代码
掌握模板是编写通用 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的预处理器。