C++(模板)
在C++中,模板是泛型编程的重要工具,用于编写通用和可重用的代码。模板主要有两种类型:函数模板和类模板。
1. 函数模板(Function Templates)
函数模板允许你定义一个函数,其操作可以应用于不同的数据类型。它们可以在编译时生成多个版本的函数,以适应不同的数据类型。
1.1 基本语法:
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
这里,template <typename T>
定义了一个模板,其中 T
是一个类型参数。max
函数可以接受任意类型的参数,只要这两个参数的类型相同。
1.2 使用示例:
int main() {
cout << max(10, 20) << endl; // 使用int
cout << max(10.5, 20.5) << endl; // 使用double
return 0;
}
C++编译器根据调用 max
函数时的参数类型自动生成相应的函数版本。
2. 类模板(Class Templates)
类模板允许你定义一个类,其数据成员和成员函数可以依赖于模板参数。这使得类可以处理不同的数据类型。
2.1 基本语法:
template <typename T>
class Stack {
private:
vector<T> elements;
public:
void push(const T& element) {
elements.push_back(element);
}
T pop() {
if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack");
T elem = elements.back();
elements.pop_back();
return elem;
}
bool empty() const {
return elements.empty();
}
};
这里,template <typename T>
定义了一个类模板,T
是一个类型参数。Stack
类可以处理任意类型的数据。
这段C++代码定义了一个模板类
Stack
,实现了一个泛型栈的数据结构。让我们逐行解析这段代码:1. 模板定义
template <typename T> class Stack {
template <typename T>
: 这行声明了一个模板类。T
是模板参数,表示栈中存储的元素类型。使用typename
或class
都可以,typename
是更常用的习惯。2. 私有成员
private: vector<T> elements;
private
: 访问控制标记,表示下面的成员只能在类的内部访问。vector<T> elements;
: 这是一个vector
容器,用于存储栈中的元素。vector
是一个标准库容器,T
是其元素类型,说明Stack
类可以存储任何类型的元素。3. 公有成员函数
push
函数
public: void push(const T& element) { elements.push_back(element); }
void push(const T& element)
: 这是一个公有成员函数,用于将元素element
压入栈中。参数const T& element
是T
类型的常量引用,避免了拷贝操作,提高了效率。elements.push_back(element);
: 将元素添加到vector
的末尾,这样实现了栈的“入栈”操作。
pop
函数
T pop() { if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack"); T elem = elements.back(); elements.pop_back(); return elem; }
T pop()
: 这是一个公有成员函数,用于从栈中移除并返回栈顶元素。if (elements.empty()) throw out_of_range("Stack<>::pop(): empty stack");
: 如果栈为空,抛出out_of_range
异常,避免在空栈上执行pop
操作。T elem = elements.back();
: 获取栈顶的元素(即vector
的最后一个元素)。elements.pop_back();
: 从vector
中移除栈顶元素,执行“出栈”操作。return elem;
: 返回被移除的元素。
empty
函数
bool empty() const { return elements.empty(); }
bool empty() const
: 这是一个公有成员函数,用于检查栈是否为空。const
关键字表明此函数不会修改类的成员数据。return elements.empty();
:empty()
是vector
的成员函数,返回true
如果vector
为空,false
如果vector
里有元素。总结
- 数据成员:
elements
是一个vector
容器,存储栈中的元素。- 成员函数:
push(const T& element)
: 将元素压入栈中。pop()
: 移除并返回栈顶的元素,若栈为空则抛出异常。empty() const
: 检查栈是否为空。这个
Stack
类模板允许你创建类型安全的栈,适用于任何数据类型。由于它是一个模板类,你可以用不同的类型实例化Stack
类,如Stack<int>
、Stack<double>
等。
2.2 使用示例:
int main() {
Stack<int> intStack;
intStack.push(1);
intStack.push(2);
cout << intStack.pop() << endl; // 输出 2
Stack<string> stringStack;
stringStack.push("hello");
stringStack.push("world");
cout << stringStack.pop() << endl; // 输出 "world"
return 0;
}
使用
Stack
模板类来创建和操作两个Stack
对象:一个用于存储int
类型的元素,另一个用于存储string
类型的元素。1. 创建
int
类型的栈对象
Stack<int> intStack;
Stack<int>
: 这里使用Stack
类模板创建一个类型为int
的栈。intStack
是这个栈的实例,专门存储int
类型的数据。2. 入栈操作
intStack.push(1); intStack.push(2);
intStack.push(1);
: 将整数1
压入intStack
中。此时栈的状态是[1]
。intStack.push(2);
: 将整数2
压入栈中。此时栈的状态是[1, 2]
,2
是栈顶元素。3. 出栈操作及输出
cout << intStack.pop() << endl; // 输出 2
intStack.pop()
: 从intStack
中移除栈顶的元素并返回它。此时栈顶元素2
被移除,栈的状态变为[1]
。返回的值2
被传递到cout
中输出。cout << intStack.pop() << endl;
: 输出2
,并换行。4. 创建
string
类型的栈对象Stack<string> stringStack;
Stack<string>
: 这里使用Stack
类模板创建一个类型为string
的栈。stringStack
是这个栈的实例,专门存储string
类型的数据。5. 入栈操作
stringStack.push("hello"); stringStack.push("world");
stringStack.push("hello");
: 将字符串"hello"
压入stringStack
中。此时栈的状态是["hello"]
。stringStack.push("world");
: 将字符串"world"
压入栈中。此时栈的状态是["hello", "world"]
,"world"
是栈顶元素。6. 出栈操作及输出
cout << stringStack.pop() << endl; // 输出 "world"
stringStack.pop()
: 从stringStack
中移除栈顶的元素并返回它。此时栈顶元素"world"
被移除,栈的状态变为["hello"]
。返回的值"world"
被传递到cout
中输出。cout << stringStack.pop() << endl;
: 输出"world"
,并换行。7. 结束程序
return 0;
return 0;
: 结束main
函数并返回0
,表示程序成功结束。总结
这段代码展示了如何使用
Stack
类模板来操作不同类型的栈对象:
- 创建了一个
int
类型的栈intStack
,进行了元素的入栈和出栈操作,并输出了出栈的结果。- 创建了一个
string
类型的栈stringStack
,进行了元素的入栈和出栈操作,并输出了出栈的结果。
Stack
类模板的使用使得栈可以存储不同类型的数据,并且所有操作都是类型安全的。
3. 模板的特性
-
模板特化(Template Specialization):
-
全特化:为特定类型提供特定实现。
template <> class Stack<bool> { // 特化版本的实现 };
-
偏特化:为模板参数的某些组合提供特定实现。
template <typename T> class Pair<T, T> { // 特化版本的实现 };
-
-
非类型模板参数:
模板参数不仅可以是类型,也可以是常量值。template <int size> class Array { int arr[size]; };
-
模板递归:
可以在模板中进行递归定义,用于编写复杂的编译时计算。
模板机制提供了极大的灵活性和重用性,是C++语言强大的特性之一。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)