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