C++ 中的模板
模板是 C++ 中一个简单但功能强大的工具。简单的想法是将数据类型作为参数传递,这样我们就不需要为不同的数据类型编写相同的代码。例如,一家软件公司可能需要 sort() 来处理不同的数据类型。我们可以编写一个 sort() 并将数据类型作为参数传递,而不是编写和维护多个代码。
C++ 添加了两个新的关键字来支持模板:‘template’和’typename’。第二个关键字总是可以用关键字’class’代替。
模板如何工作?
模板在编译器时展开。这就像宏。不同之处在于,编译器会在模板扩展之前进行类型检查。这个想法很简单,源代码只包含函数/类,但编译后的代码可能包含同一函数/类的多个副本。
函数模板我们编写了一个可用于不同数据类型的通用函数。函数模板的示例是 sort()、max()、min()、printArray()。
了解更多关于C++ 中的泛型
#include <iostream>
using namespace std;
// One function works for all data types. This would work
// even for user defined types if operator '>' is overloaded
template <typename T>
T myMax(T x, T y)
{
return (x > y)? x: y;
}
int main()
{
cout << myMax<int>(3, 7) << endl; // Call myMax for int
cout << myMax<double>(3.0, 7.0) << endl; // call myMax for double
cout << myMax<char>('g', 'e') << endl; // call myMax for char
return 0;
}
输出:
7
7
g
下面是在 C++ 中使用模板 实现冒泡排序的程序:
// CPP code for bubble sort
// using template function
#include <iostream>
using namespace std;
// A template function to implement bubble sort.
// We can use this for any data type that supports
// comparison operator < and swap works for it.
template <class T>
void bubbleSort(T a[], int n) {
for (int i = 0; i < n - 1; i++)
for (int j = n - 1; i < j; j--)
if (a[j] < a[j - 1])
swap(a[j], a[j - 1]);
}
// Driver Code
int main() {
int a[5] = {10, 50, 30, 40, 20};
int n = sizeof(a) / sizeof(a[0]);
// calls template function
bubbleSort<int>(a, n);
cout << " Sorted array : ";
for (int i = 0; i < n; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}
输出:
排序数组:10 20 30 40 50
类模板与函数模板一样,类模板在类定义独立于数据类型的内容时很有用。可用于 LinkedList、BinaryTree、Stack、Queue、Array 等
类。以下是模板 Array 类的简单示例。
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T *ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
template <typename T>
Array<T>::Array(T arr[], int s) {
ptr = new T[s];
size = s;
for(int i = 0; i < size; i++)
ptr[i] = arr[i];
}
template <typename T>
void Array<T>::print() {
for (int i = 0; i < size; i++)
cout<<" "<<*(ptr + i);
cout<<endl;
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
Array<int> a(arr, 5);
a.print();
return 0;
}
输出:
1 2 3 4 5
模板可以有多个参数吗?
是的,就像普通参数一样,我们可以将不止一种数据类型作为参数传递给模板。以下示例演示了相同的内容。
- CPP
#include<iostream>
using namespace std;
template<class T, class U>
class A {
T x;
U y;
public:
A() { cout<<"Constructor Called"<<endl; }
};
int main() {
A<char, char> a;
A<int, double> b;
return 0;
}
输出:
构造函数调用
构造函数调用
我们可以为模板参数指定默认值吗?
是的,就像普通参数一样,我们可以为模板指定默认参数。以下示例演示了相同的内容。
#include<iostream>
using namespace std;
template<class T, class U = char>
class A {
public:
T x;
U y;
A() { cout<<"Constructor Called"<<endl; }
};
int main() {
A<char> a; // This will call A<char, char>
return 0;
}
输出:
构造函数调用
函数重载和模板有什么区别?
函数重载和模板都是 OOP 多态特性的例子。当多个函数执行相似的操作时使用函数重载,当多个函数执行相同的操作时使用模板。
当模板类/函数中有静态成员时会发生什么?
模板的每个实例都包含自己的静态变量。有关更多详细信息,请参阅模板和静态变量。
什么是模板专业化?
模板专业化允许我们为特定的数据类型使用不同的代码。有关更多详细信息,请参阅模板专业化。
我们可以将非类型参数传递给模板吗?
我们可以将非类型参数传递给模板。非类型参数主要用于为模板的特定实例指定最大值或最小值或任何其他常量值。关于非类型参数需要注意的重要一点是,它们必须是 const。编译器必须在编译时知道非类型参数的值。因为编译器需要在编译时为指定的非类型值创建函数/类。在下面的程序中,如果我们将 10000 或 25 替换为变量,则会出现编译器错误。请看这个。
下面是一个 C++ 程序。
// A C++ program to demonstrate working of non-type
// parameters to templates in C++.
#include <iostream>
using namespace std;
template <class T, int max>
int arrMin(T arr[], int n)
{
int m = max;
for (int i = 0; i < n; i++)
if (arr[i] < m)
m = arr[i];
return m;
}
int main()
{
int arr1[] = {10, 20, 15, 12};
int n1 = sizeof(arr1)/sizeof(arr1[0]);
char arr2[] = {1, 2, 3};
int n2 = sizeof(arr2)/sizeof(arr2[0]);
// Second template parameter to arrMin must be a constant
cout << arrMin<int, 10000>(arr1, n1) << endl;
cout << arrMin<char, 256>(arr2, n2);
return 0;
}
输出:
10
1