模板是泛型编程的实现方式之一,只需要写一份便可以套用不同类型的类、函数、变量。
(以下涉及的代码有部分是从https://blog.csdn.net/m0_64361907/article/details/126788130 处转载)
模板函数
这是普通的 c 语言写交换函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include<iostream> using namespace std;
void Swapi(int* a, int* b){ int tmp = *a; *a = *b; *b = tmp; }
void Swapd(double* a, double* b){ double tmp = *a; *a = *b; *b = tmp; }
int main(){ int a = 1, b = 2; Swapi(&a, &b); double c = 1.1, d = 2.2; Swapd(&c, &d);
return 0; }
|
可以看到,对于不同的参数类型,我们要写多个不同的交换函数。
而在 c 语言中,是不支持函数重载的,所以不同的交换函数无法使用同样的函数名实现重载
c++写交换函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include<iostream> using namespace std;
void Swap(int& x, int& y){ int tmp = x; x = y; y = tmp; }
void Swap(double& x, double& y){ double tmp = x; x = y; y = tmp; }
int main(){ int a = 1, b = 2; Swap(a, b);
double c = 1.1, d = 2.2; Swap(c, d); return 0; }
|
C++ 中有了引用和函数重载,但是在实现不同类型参数的交换函数时仍然很麻烦。
所以就有了模板
使用模板的交换函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<iostream> using namespace std;
template <class T> void Swap(T& x, T& y){ T tmp = x; x = y; y = tmp; }
int main(){ int a = 1, b = 2; Swap(a, b);
double c = 1.1, d = 2.2; Swap(c, d); return 0; }
|
如此,编译器能够自己套用对应的参数类型。
显示实例化和隐式实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<iostream> using namespace std;
template <class T> T Add(const T& x,const T& y){ return x + y; }
int main(){ int a = 1, b = 2; double c = 1.1, d = 2.2;
cout << Add(a, b) << endl; cout << Add(c, d) << endl;
cout << Add<int>(a, c) << endl; cout << Add<double>(b, d) << endl;
cout << Add(a, (int)c) << endl; return 0; }
|
不告诉编译器参数类型的是隐式实例化
指定了参数类型的是显式实例化
类模板
此处将会以一个建议的 vector 容器的模板类实现作为例子。
实现 vector 落后的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| typedef int VDateType; class vector{ public: private: VDateType* _a; size_t _size; size_t _capacity; };
int main(){ vector v1; vector v2; return 0; }
|
以前的实现方式是这样的,但我们不能让v1类型为 int,v2类型为 double。
使用类模板的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include<iostream> #include<assert.h> using namespace std;
namespace kcc{ template<class T> class vector{ public: vector() :_a(nullptr) , _size(0) , _capacity(0) {}
~vector(){ delete[] _a; _a = nullptr; _size = _capacity = 0; }
void push_back(const T& x){ if (_size == _capacity){ int newcapacity = _capacity == 0 ? 4 : _capacity * 2; T* tmp = new T[newcapacity]; if (_a){ memcpy(tmp, _a, sizeof(T) * _size); delete[] _a; } _a = tmp; _capacity = newcapacity; }
_a[_size] = x; ++_size; }
T& operator[](size_t pos); size_t size(); private: T* _a; size_t _size; size_t _capacity; };
template<class T> T& vector<T>::operator[](size_t pos){ assert(pos < _size);
return _a[pos]; }
template<class T> size_t vector<T>::size(){ return _size; } }
int main(){ kcc::vector<int> v1; v1.push_back(1); v1.push_back(2); v1.push_back(3); v1.push_back(4);
for (size_t i = 0; i < v1.size(); ++i){ v1[i] *= 2; } cout << endl;
for (size_t i = 0; i < v1.size(); ++i){ cout << v1[i] << " "; } cout << endl;
kcc::vector<double> v2; v2.push_back(1.1); v2.push_back(2.2); v2.push_back(3.3); v2.push_back(4.4);
for (size_t i = 0; i < v2.size(); ++i){ cout << v2[i] << " "; } cout << endl;
return 0; }
|