C++模板 初阶
模板介绍🧐
C++中,我们写一个交换函数,使用函数重载可以解决不同类型交换这一问题,不过类型有那么多种,全部写出来费时费力,可维护性还低,所以C++出现了模板来更好的解决类型问题。
我们可以将模版看做生活中的模具,它的外型是固定的,填入不同的材料来获得不同的铸件。模板也是如此,函数功能一致,只是传入的类型可以随意更改。这也是我们的泛型编程的基础——编写与类型无关的通用代码,可以对该代码进行复用。
模板又分为函数模板和类模板,我们先来介绍函数模板。
函数模板🧐
格式🔎
使用函数模板可以让编译器自动推出类型,格式为:
template<typename T> //typename是定义模板的关键字,也可以用class void Swap( T& left, T& right) { T temp = left; left = right; right = temp; }
函数模板是一个蓝图,它本身并不是函数。在编译阶段时,需要编译器根据传入参数自动推出类型,然后实例化生成对应函数。如该代码,两个Swap函数调用的不是同一函数。
template<class T> void Swap(T& a, T& b) { T c = a; a = b; b = c; } int main() { int a = 1; int b = 2; char c = 'c'; char d = 'd'; Swap(a, b); Swap(c, d); return 0; }
实例化🔎
实例化也分为隐式实例化和显示实例化,我们让模板自己推类型就是隐式实例化,而当模板无法自己推出类型时(如传两个不同类型的参数)就需要我们显示实例化(或者强转)。
template<class T> T Add(const T& left, const T& right) { return left + right; } int main() { int a = 10; double b = 20.0; Add<int>(a, b); //如果不显示实例化,编译器会报错 return 0; return 0; }
匹配规则🔎
当函数模板与函数重名时,并且函数类型相匹配,那么会优先调用该函数,如果没有匹配的或者有更加匹配的就会调用函数模板,简而言之谁最匹配调用谁。
template<class T1,class T2> T1 Add(T1 left, T2 right) { cout << "template T1 T2" << endl; return left + right; } template<class T> T Add(T left, T right) { cout << "template" << endl; return left + right; } int Add(int left, int right) { cout << "int" << endl; return left + right; } int main() { int a = 10; int b = 20; Add(a, b); //有对应类型函数,优先调用函数 Add<int>(a,b); //有对应类型函数,但显示实例化,优先调用模板 Add(1, 2.0); //没有对应类型函数,优先调用对应参数模板 return 0; }
类模板🧐
格式🔎
template<class T1, class T2, ..., class Tn> class 类模板名 { // 类内成员定义 }; //示例 以栈为例,C语言中需要typedef更改类型,C++用类模板就可以搞定 //Stack不是具体的类,需要实例化 template<class T> class Stack { public: Stack(size_t capacity = 4) { _a = new T[capacity]; _capacity = capacity; _size = 0; } void Push(T data) { _a[_size] = data; _size++; } private: T* _a; //这样_a就可以接收不同类型数据 int _capacity; int _size; };
实例化🔎
类模板需要显示实例化
int main() { Stack<int> st1; //Stack为类名 Stack<int>才是类型 Stack<double> st2; st1.Push(1); st2.Push(1.2); return 0; }
结尾👍
以上便是模板的初阶介绍,如果有疑问或者建议都可以私信笔者交流,大家互相学习,互相进步!🌹