目录
引言
在 C++ 中,模板(Template)是一种强大的特性,它允许我们编写通用的代码,以处理不同的数据类型。模板分为函数模板和类模板,本文将结合实际代码,详细解析这两种模板,并以代码中的 Stack
类模板为例进行深入探讨。
函数模板
在c语言中若要实现不同类型的交换,就要像这样实现多个函数(c语言甚至不支持函数重载)。
这样显得十分繁琐,于是c++引入了一个函数模板的概念。
基本概念
函数模板是一种通用的函数定义,它可以用于不同的数据类型。通过模板参数,我们可以在函数定义中使用一个或多个通用类型,而不是具体的数据类型。
代码示例
template <class T>
T Add(const T& left, const T& right)
{
return left + right;
}
template <class T1, class T2>
T2 Add(const T1& left, const T2& right)
{
return left + right;
}
解析
template <class T>
是模板声明,T
是模板参数,可以代表任意数据类型。Add
函数接受两个T
类型的参数,并返回它们的和。- 第二个
Add
函数模板接受两个不同类型的参数T1
和T2
,并返回T2
类型的结果。
实例化
函数模板的实例化可以通过两种方式进行:
- 推导实例化:编译器根据函数调用时的参数类型自动推导模板参数的具体类型。
int a = 10, b = 20; cout << Add(a, b) << endl; // 推导实例化为 Add<int>
- 显示实例化:在函数调用时明确指定模板参数的具体类型。
double c = 10.1; cout << Add<int>(a, c) << endl; // 显示实例化为 Add<int, double>
在某些特殊的情况下,必须使用显式实例化来指定模板参数类型,如:
template <class T> T Func(int n) { return new T[n]; } int main() { double* p1 = Func<double>(10); }
类模板
基本概念
类模板是一种通用的类定义,它允许我们创建可以处理不同数据类型的类。与函数模板类似,类模板也使用模板参数来表示通用类型。
代码示例
template <class T> class Stack { public: Stack(int n = 4) :_array(new T[n]) ,_size(0) ,_capacity(n) {} ~Stack() { delete[] _array; _array = nullptr; _size = _capacity = 0; } void Push(const T& x) { if(_size == _capacity) { T* tmp = new T[_capacity * 2]; memcpy(tmp, _array, sizeof(T) * _size); delete[] _array; _array = tmp; _capacity *= 2; } _array[_size++] = x; } void Print() { for(size_t i = 0; i < _size; i++) { cout << _array[i] << " "; } cout << endl; } void Pop() { --_size; } private: T* _array; size_t _size; size_t _capacity; };
解析
template <class T>
是类模板的声明,T
是模板参数,表示栈中存储的数据类型。Stack
类包含一个动态数组_array
,用于存储栈中的元素,以及_size
和_capacity
分别表示栈的当前大小和容量。Push
函数用于向栈中添加元素,如果栈已满,则进行扩容操作。Print
函数用于打印栈中的所有元素。Pop
函数用于从栈中移除栈顶元素。
实例化
类模板必须进行显式实例化,即在创建对象时明确指定模板参数的具体类型。
Stack<int> st;
st.Push(1);
st.Push(2);
st.Push(3);
st.Push(4);
st.Print();
st.Pop();
st.Print();
总结
函数模板和类模板是 C++ 中非常重要的特性,它们可以帮助我们编写通用的代码,提高代码的复用性和可维护性。函数模板可以根据函数调用时的参数类型自动推导或显式指定模板参数的具体类型,而类模板必须进行显式实例化。通过使用模板,我们可以编写出更加灵活和高效的代码。
以上就是对 C++ 函数模板和类模板的详细解析,希望对你有所帮助。