感谢你的阅读!!!
目录
感谢你的阅读!!!
举个例子:
template
有什么意义为什么要用模板
与typedef的区别
使用方法
模板:隐式实例化与显示实例化
和非模板函数以及多个模板类函数重载情况
类模板声明与定义
举个例子:
在古代模板就一块板子,在一本书的复制,如果靠手写不止到猴年马月才可以推广,但是在伙子印刷术的出现,大大的加快了书籍的推广。。。。
template <typename NAME>
使用方法 关键字template <typename Name>
template <typename Ty>
Ty add(const Ty&a,const Ty&b)
{
return a+b;
}
int main()
{
cout<<add(1,2)<<endl;
return 0;
}
在主函数中打印表达式中的add函数会根据传入的形参类型确定类型,然后再参数出自动推导类型。
那有个问题来了,模板是函数吗?
其实很好回答的,跨海大桥图纸是跨海大桥吗?不是的
让我们看下面这段代码
我们将i1,i2、d1,d2 、ch1,ch2,分别传入swap函数进行交换,运行代码
发现确实交换了,那么可以说我们的模板其实是一个函数咯?其实模板只是模板而这里是使用了根据模板造的3个Swap函数
根据传入的参数类型编译器推演类型,确定生成哪一类临时函数进行完成任务。
所以这里的函数其实是3个不同类型的Swap()。
有什么意义为什么要用模板
为了更快,更方便的使用代码完成任务,避免一直写一些数据类不同而任务相同的函数。
将程序员从任务相同数据类型不同的函数中解放出来。
与typedef的区别
如果是typedef为类型其别名的话,它其实也是为了便利函数,但是在上述的代码中它是十分不利的
一个函数只能完成一个类型数据的交换,如果需要同时交换数据那只能写多个Swap函数进行函数重载了,但是加上自定义类型的话,那么要写的Swap重载函数需要太多太多的,但是使用模板进行书写,就只关心传入的数据了
使用方法
template关键字+<class/typename name>注意这里的class不能使用struct代替!!!!!
函数/类。
模板:隐式实例化与显示实例化
隐式实例化:
template <typename Ty>
Ty Add(const Ty& a, const Ty& b)
{
return a + b;
}
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
没有指定Add函数参数类型,编译器自动识别实参类型进行推演后实例化Swap函数,进行完成任务。
Ty Add(const Ty& a, const Ty& b)
{
return a + b;
}
//...1和2传入,推演类型为int,模板实例化
int Add(const int& a, const int& b)
{
return a + b;
}
显示实例化
有一种情况,如果Add的两个实参类型不一样
Ty Add(const Ty& a, const Ty& b)
{
return a + b;
}
int main()
{
cout << Add(1, 2.2) << endl;//int,double
return 0;
}
这个时候编译器将不知道应该为哪一种函数类型
解决方法一:传入数据强制类型转换
Add(1,(int)1.1);
//或者
Add((double)1,1.1);
虽然可以完成任务,但是加大了程序员的负担,不推荐
解决方法二:设置两个模板。
template <typename Ty,typename Tx>
Ty Add(const Ty& a, const Tx& b)
{
return a + b;
}
int main()
{
cout << Add(1, 2.2) << endl;
这样虽然解决了传入不同参数的方法,但是在返回值的时候是根据a的数据类型为返回值类型的,加大了我们程序员的复杂性。一般推荐
解决方法三:使用显示模板实例化
显示的实例化,不在根据实参类型实例化我们的函数,根据我们自己的要求实例化函数
template <typename Ty,typename Tx>
Ty Add(const Ty& a, const Tx& b)
{
return a + b;
}
int main()
{
cout << Add<int,int>(1, 2.2) << endl;
无论Add类型如何,我们的实例化的函数形参类型都是int,int类型。
这样我们可以更加随心所欲的使用模板实例化函数了。
和非模板函数以及多个模板类函数重载情况
与非模板函数:
当模板函数与我们的非模板函数同名是,会根据类型函数调用函数。
运行代码:
发现调用
为什么会发生这样的事情呢?因为推演有时间的
调用Add函数的时候会先看代码中是否有参数类型匹配的函数定义,如果有就会调用匹配函数,如果没有才会根据模板实例化相应函数,然后调用实例化函数。
与模板函数
因为推演会有时间上的损耗,所以两个模板不同名字相同的函数会有区别
也是根据实参类型,使用不同的模板,这里我们不深究,这样的情况我们在日常工作中很少遇见,找到就好了。
类模板必须显示实例化
为什么类模板必须显示实例化?
为了类中出现任何成员函数中可以使用模板,必须显示实例化模板:必须提供模板参数,以便编译器可以生成实际的类(或函数,来自函数模板)。
如st1我们隐式实例化,我们就无法知道我们的TData的替换是说明类型数据了,这样在类成员函数中以及成员变量我们就不知道该类型是什么类型了,所以我们的必须显示实例化类实例化对象,如st2,我们就实例化了保存char类型一个类=>栈。否则,我们将不知道该栈存储的是什么数据了。
所以,如果说类是对象的图纸,那么类模板就是类的图纸。对类也要实例化产生实例的类。
这里有一个注意的地方!!!
类模板声明与定义
类模板声明与定义不要分离(声明在.h,定义在.cpp )
也就是说,一个类模板实现,函数的声明与定义不能分别在不同的文件中。
但是同一个文件可以实现类模板成员函数声明定义分离。但是我们在类域外定义的时候也要进行模板的操作
感谢你的阅读!!!