C++ 模板(初级)
目录1. 泛型编程2. 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板原理2.4 函数模板的实例化2.5 模板参数的比配原则3. 类模板3.1 类模板的定义模式3.2 类模板的实例化1. 泛型编程在C中有函数重载相同名字的函数名可以通过参数的不同类型构成函数重载。void Swap(int a, int b) { int tmp a; a b; b tmp; } void Swap(double a, double b) { double tmp a; a b; b tmp; } //...就如这个 Swap 函数进行实现两个数值的交换就需要不同类型的 Swap 的函数都需要进行函数重载如果只是对C中的内置类型进行编译就已经很麻烦了如果还算上自定义类型那编程的功能就会变得更加麻烦。所以在C中就存在模板的概念通过编译一个 Swap 的函数就一个解决繁琐的过程。泛型编程编写与类型无关的通用代码是代码服用的手段模板是泛型编程的基础。2. 函数模板2.1 函数模板概念函数模板是 C 泛型编程的核心工具之一。它允许我们编写一个通用的函数定义该定义可以适用于多种不同的数据类型而无需为每种类型都重写一遍函数。简单来说函数模板是一个蓝图或公式编译器会根据这个蓝图在编译时根据实际使用的数据类型生成具体的函数代码这个过程称为实例化。2.2 函数模板格式template typename T void Swap(T a, T b) { T tmp a; a b; b tmp; }这里的template typename T声明了一个类型参数T。当我们调用Swap(int_a, int_b)时编译器会将T推导为int并生成一个处理int类型的Swap函数。调用Swap(double_a, double_b)时则会生成处理double类型的版本。因此函数模板的本质是“参数化类型”它将数据类型本身作为参数实现了代码的高度复用是解决函数重载冗余问题的优雅方案。补充template class T也是可行的两种写法都是相同注意不可用struct代替。template typename T template class T这两个只对下一行函数或者类可以使用使用函数模板都需要重新编写一次这一行代码无法跨行使用。2.3 函数模板原理函数模板的运行原理就是通过传参的数值编译器对对应的类型配对编译器再生成出对应类型传参的相关函数进行配对达到函数成功运行目的。2.4 函数模板的实例化#include iostream #include stdlib.h using namespace std; template typename T T add(T a,T b) { return a b; } int main() { int a 10; int b 20; double c 20.0; double d 10.50; return 0; }以上面的代码为例b add(a, b);//true整形与整形相互加减是可行的如果出现整形和浮点型进行加减就会导致报错提醒。解决方案两种对传参的强制类型转换。在C中这种操作叫作函数模板实例化这种操作又分为隐式实例化和显示实例化。c add(a, (int)c);//隐式实例化 //把对应的浮点型转成整形int a addint(c, b);//显示实力化 //把所有的传参转成整形int2.5 模板参数的比配原则一个非模板函数可以与模板同名函数共存。在函数调用的时候如果调用的函数参数与非模板函数一致优先会调用非模板函数实在没有在会调用模板函数。#include iostream #include stdlib.h using namespace std; template typename T void Swap(T a, T b) { T tmp a; a b; b tmp; cout Swap T 模板函数 endl; } void Swap(int a, int b) { int tmp a; a b; b tmp; cout Swap int 非模板函数 endl; } void Swap(double a, double b) { double tmp a; a b; b tmp; cout Swap double 非模板函数 endl; } template typename T T add(T a,T b) { cout add T 模板函数 endl; return a b; } int main() { int a 10; int b 20; Swap(a, b); double c 20.0; double d 10.50; Swap(c, d); b add(a, b); c add(a, (int)c); a addint(c, b); return 0; }输出结果3. 类模板3.1 类模板的定义模式class Stack { public: Stack(int a 4) :_arr(new int[a]), _size(0), _capacity(a) {} ~Stack() { delete[] _arr; _size 0; _capacity 0; } private: int* _arr; int _size; int _capacity; };像这种Stack的类类型只能申请出int的相关的类型在这编译器了也所有跟Stack相关的类类型都是以int的相关的类类型如果只是更改在编程中进行更改成char*那么所有向相关的类型都只能变成char相关的类类型无法做到一个我想要一个int类型就是int类型的一个想要char类型的做到 2 个及以上的操作。所有就需要到类模板的出现。template class A class Stack { public: Stack(int a 4) :_arr(new A[a]), _size(0), _capacity(a) {} ~Stack() { delete[] _arr; _size 0; _capacity 0; } private: A* _arr; int _size; int _capacity; };补充定义声明分离需要具体操作不建议定义声明分离容易报错。// test.h template class A class Stack { public: Stack(int a 4); void Puch(A a0); ~Stack(); private: A* _arr; int _size; int _capacity; }; // test.cpp #include test.h template class A StackA(int a) :_arr(new A[a]), _size(0), _capacity(a) {} template class A void StackT::Push(A a) { //... } template class A ~StackA() { delete[] _arr; _size 0; _capacity 0; }3.2 类模板的实例化// Stack 是类名 Stackint 才是类型 Stackint str1; //int Stackdouble str2; //double