当前位置:首页 » 《随便一记》 » 正文

【C++】模板

26 人参与  2023年04月30日 17:18  分类 : 《随便一记》  评论

点击全文阅读


目录

前言

1.函数模板

1.1使用

1.2实现逻辑 

1.3实例化

1.4匹配规则

2.类模板

2.1使用

实例化


前言

?️照以前的想法,若我们想实现一个交换函数,需要这样写。

void swap(int& x, int& y){int tmp = x;x = y;y = tmp;}int main(){int a = 5, b = 6;swap(a, b);return 0;}

?️若想写通用的交换函数呢?根本没完没了,换一个类型就要重新写一次,就算有了函数重载也不能减少多少工作量。

void swap(int& x, int& y){int tmp = x;x = y;y = tmp;}void swap(char& x, char& y){int tmp = x;x = y;y = tmp;}void swap(double& x, double& y){int tmp = x;x = y;y = tmp;}......

?️就像古代最早出现的印刷术那样,使用一个模板可以去除掉那些大量并重复的工作。落实到语言中则诞生了模板(泛型编程)

1.函数模板

1.1使用

?️想要将这个函数定义成模板只需要在函数上加上这句话:template<class T ...> 其中参数的个数取决于实际需要的个数。

?️其中的 class 还可以使用 typename 替换,二者都是定义模板参数关键字,区别不大,但是不可以使用 struct 

?️这样子,我们便可以使用模板对上面交换函数进行修改。

template<class T>void swap(T& x, T& y){T tmp = x;x = y;y = tmp;}

?️我们可以将这个 想象成一个抽象的数据类型,他具体是什么我们不知道,但之后这个 会自己进行推演并转化成传入的类型。

1.2实现逻辑 

?️让我们思考一下,以下两次 swap 调用的是同一个函数吗?

template<class T>void swap(T& x, T& y){T tmp = x;x = y;y = tmp;}int main(){int a = 5, b = 6;double c = 5.5, d = 6.6;swap(a, b);swap(c, d);return 0;}

?️通过查看汇编,我们可以发现,其中调用的函数地址并不相同,即调用了两个不同的函数。 

 ?️我们曾经将类比作蓝图,对象比作楼房。其实模板也是一样的,它会根据传入参数的不同类型进行推演,之后再进行实例化,生成不同版本的代码。因此不同类型的参数调用的函数并不是同一份

?️本质上不同类型的函数还是要实现一份的,但使用模板就将实例化这个重复的工作交给了编译器,由编译器代我们实现。

1.3实例化

?️用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化显式实例化

隐式实例化:让编译器根据实参推演模板参数的实际类型。显式实例化:在函数名后的<>中指定模板参数的实际类型。

?️若模板中只有一个数据类型,用两个类型的参数进行调用,编译器不知道该推演成哪个类型,便会出现歧义。

?️可以传参时强制类型转换,使其满足隐式实例化。也可以指定模板参数的实际类型,让参数发生隐式类型转换,使其满足显式类型转换。

1.4匹配规则

?️一个非模板函数和一个同名的函数模板可以同时存在,那么在这种情况下会调用哪一个函数呢?

template<class T>int add(const T& x,const T& y){return x + y;}int add(int x, int y){return x + y;}int main(){int a = 5, b = 6;add(a, b);return 0;}

?️为了节约程序开销,编译器会优先选择成本较低的参数更加匹配的的函数进行调用。

2.类模板

2.1使用

?️类模板的定义与函数模板类似,根据需要定义任意数量的模板参数,之后便可以使用模板参数作为抽象的数据类型到类中。

template<class T>class A{public:A(T a = 1):_a(a){}private:T _a;};int main(){A<int> a1;return 0;}

?️类模板中函数放在类外进行定义时,需要加模板参数列表。

template<class T>class A{public:A(T a = 1):_a(a){}~A();           //类中声明函数private:T _a;};template<class T>   //需加上函数参数列表A<T>::~A()          //类外定义函数{ _a = 0;}int main(){A<int> a1; return 0;}

?️在实例化之前,当前模板类并不能算作一个真正的类,只是编译器根据被实例化的类型生成具体类的模具 。

实例化

?️与函数模板实例化不同,类模板实例化时需要在类模板名字后加上 <> ,<>中放的是实例化的类型。因为编译器无法推演出其中的类型应该是如何对应的,因此需要手动指定

A是类名,A<int>才是类型


?️好了,今天模板基础内容的讲解到这里就结束了,如果这篇文章对你有用的话还请留下你的三连加关注。


点击全文阅读


本文链接:http://zhangshiyu.com/post/60167.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1