C++超详细介绍模板
1. 什么是模板
模板是一种通用的程序设计语言工具。它使程序员可以编写出适用于多种不同数据类型的函数或类。
在 C++ 中,模板可以定义函数模板和类模板。函数模板通常用于编写可以处理多种数据类型的函数,而类模板则用于创建可以适用于多种数据类型的类。
1.1 函数模板
函数模板可以定义一类函数,其中参数的类型和个数可以不确定。在定义函数模板时,需要使用 template
关键字,指定模板参数。例如:
template <typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
上面的代码定义了一个 max
函数模板,其中输入参数为两个类型相同的值 a
和 b
,输出为两个值中的较大值。
使用函数模板时,需要在调用函数时指定模板参数。例如:
int main()
{
int x = 3, y = 5;
double a = 2.5, b = 1.6;
std::cout << max<int>(x, y) << std::endl;
std::cout << max<double>(a, b) << std::endl;
return 0;
}
上面的代码分别输出了 x
和 y
的最大值以及 a
和 b
的最大值。
1.2 类模板
类模板可以定义一类类,其中数据类型可以不确定。在定义类模板时,需要使用 template
关键字,指定模板参数。例如:
template <typename T>
class Stack
{
public:
Stack();
void push(T value);
T get();
bool empty();
private:
T* data;
int count;
};
上面的代码定义了一个 Stack
类模板,其中数据类型为 T
。Stack
类有两个公共函数 push
和 get
,可以将数据压入栈中或弹出栈中的数据。
使用类模板时,需要在声明类时指定模板参数。例如:
int main()
{
Stack<int> stack1;
stack1.push(1);
stack1.push(2);
std::cout << stack1.get() << std::endl;
Stack<char> stack2;
stack2.push('a');
stack2.push('b');
std::cout << stack2.get() << std::endl;
return 0;
}
上面的代码分别定义了两个不同的 Stack
类,其中一个将 int
类型数据压入栈中,一个将 char
类型数据压入栈中。
2. 模板详解
2.1 模板参数
模板参数分为两类:类型参数和非类型参数。
2.1.1 类型参数
类型参数可以是任何类型,但不包括函数类型和数组类型。类型参数可以使用 typename
或 class
关键字进行声明。例如:
template <typename T>
void f(T x);
template <class T>
void g(T x);
上面的代码分别使用了 typename
和 class
关键字声明了类型参数 T
。
2.1.2 非类型参数
非类型参数可以是任何常量表达式,包括整数、枚举、指针、成员指针等。在声明非类型参数时,需要使用 typename
和 class
关键字。例如:
template <typename T, int N>
class Array
{
public:
T data[N];
int size() { return N; }
};
上面的代码定义了一个 Array
类模板,其中包含一个类型参数 T
和一个非类型参数 N
。Array
类模板用于创建一个可以容纳 N
个元素的数组。
2.2 模板类型推导
在调用函数模板时,可以忽略模板参数的指定,编译器会通过调用时传递的参数进行类型推导。例如:
template <typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
int x = 3, y = 5;
double a = 2.5, b = 1.6;
std::cout << max(x, y) << std::endl;
std::cout << max(a, b) << std::endl;
return 0;
}
上面的代码在调用 max
函数时没有指定模板参数,编译器通过调用时传递的参数推导出模板参数的类型。
2.3 模板特化
在某些情况下,需要为某些特定类型的数据提供特殊的处理方式。这时可以使用模板特化。
模板特化会在泛化模板的基础上提供一种或多种具体的实现。例如:
// 泛化模板
template <typename T>
void print(T a)
{
std::cout << a << std::endl;
}
// 特化模板
template <>
void print<const char*>(const char* a)
{
std::cout << "specialization: " << a << std::endl;
}
int main()
{
print(123); // 调用泛化模板
print("hello"); // 调用特化模板
return 0;
}
上面的代码定义了一个 print
函数模板,其中泛化模板的参数类型为 T
,特化模板的参数类型为 const char*
。当传入 const char*
类型的参数时,会调用特化模板。
3. 示例
3.1 Stack 类模板示例
#include <iostream>
template <typename T>
class Stack
{
public:
Stack() : data(new T[100]), count(0) {}
void push(T value) { data[count++] = value; }
T get() { return data[--count]; }
bool empty() { return count == 0; }
private:
T* data;
int count;
};
int main()
{
Stack<int> stack1;
stack1.push(1);
stack1.push(2);
std::cout << stack1.get() << std::endl;
Stack<char> stack2;
stack2.push('a');
stack2.push('b');
std::cout << stack2.get() << std::endl;
return 0;
}
上面的代码定义了一个 Stack
类模板,用于创建一个可以容纳任意数据类型的栈。在 main
函数中分别对 Stack<int>
和 Stack<char>
进行了测试。
3.2 Vector 类模板示例
#include <iostream>
#include <vector>
template <typename T>
void printVector(std::vector<T>& vec)
{
for (auto i = vec.begin(); i != vec.end(); ++i)
{
std::cout << *i << " ";
}
std::cout << std::endl;
}
int main()
{
std::vector<int> vec1 = { 1, 2, 3 };
std::vector<char> vec2 = { 'a', 'b', 'c' };
printVector(vec1);
printVector(vec2);
return 0;
}
上面的代码定义了一个 printVector
函数模板,用于输出任意类型的 std::vector
。在 main
函数中分别对 std::vector<int>
和 std::vector<char>
进行了测试。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++超详细介绍模板 - Python技术站