return x+y;

}
double add(double x,double y)
{
return x+y;
}
int add(char x,char y)
{
return x+y;
}
int main()
{
cout<<add(1,2)<<endl;
cout<<add(3.1,2.3)<<endl;
cout<<add(‘a’,‘2’)<<endl;
return 0;
}


tips: int 和 char 可以隐式转换


我们如何只写一个函数就能实现下面三种不能类型数据的相加呢?


这里就要用到模板的知识,那我们来看模板。


**一.模板**


c++模板:是支持参数多态化的工具。


实质:设计一种通用类型的函数或类,在函数或类使用时,让数据成员,成员函数,函数返回值在实际使用时可以是任意类型。


目的:让程序员编写与类型无关的代码,是范型编程的基础。


函数模板:


        针对函数参数类型不同的函数。


类模板:


        针对数据成员,成员函数数据类型,参数类型不同的类


1.函数模板语法结构:


 templata <类型模板形参列表>类型模板形参 函数名(<形参列表>)


注意:


               templata:模板说明的关键字


                <类型模板形参列表>:用class或typename定义的变量,多个模板形参之间以空格隔开


                1.class T1:定义类型模板形参 T1,用来代替函数的相关数据类型。


                eg:


                        template<class T1>T1 add(T1 X,T1 Y);


把开头的例子用模板实现:


       



#include
using namespace std;
templateT1 add(T1 ,T1);//函数模板声明
template //函数模板声明
T1 add(T1 x,T1 y) //函数模板定义
{
return x+y;
}
int main()
{
cout<<add(1,2)<<endl;
cout<<add(3.1,2.3)<<endl; //函数模板的 隐式调用,自动匹配数据类型
cout<<add(‘a’,‘2’)<<endl;
return 0;
}


typename与class  
 原来C++只有class,但是对于初学者理解容易与类定义混淆  
 为了方便理解,后面的版本是加入了typename关键字方便教学使用,学校C++教材上有提过  
 有隐式调用就有显示调用


**下面就是显示调用**



#include
using namespace std;
templateT1 add(T1 ,T1);//函数模板声明
template //函数模板声明
T1 add(T1 x,T1 y) //函数模板定义
{
return x+y;
}
int main()
{
cout<<add(1,2)<<endl;
cout<<add(3.1,2.3)<<endl; //函数模板的 隐式调用,自动匹配数据类型
cout<<add(‘a’,‘2’)<<endl;
cout<<add<>(2,5)<<endl; //函数模板的显示调用
cout<<add(5,6)<<endl; //显示调用,指定模板性参 为int,是将int传递给了T1
cout<<add(3.12 ,4.1)<<endl;
return 0;
}


**如果是两个不同类型的数相加可以实现吗?**


答案也是可以的。


例子:



#include
using namespace std;
template<class T1,class T2>
T1 add(T1 x,T2 y)
{
return x+y;
}
int main()
{
cout<<add(2.1,2)<<endl;
cout<<add<>(2,2.1 )<<endl;
cout<<add<char,int>(‘a’,1)<<endl;

return 0;

}


**还可以这样写在声明处定义,带默认参数的形参**



#include
using namespace std;
template<class T1,class T2=float>
T2 add(T1 x,T2 y)
{
return x+y;
}
int main()
{
cout<<add(2.1,2)<<endl;
cout<<add<>(2,2.1 )<<endl;
cout<<add<char,int>(‘a’,1)<<endl;
cout<<add(‘b’,2.1)<<endl;

return 0;

}


**自动匹配的优先级高于默认,因此模板形参的默认参数无意义。**



**存在即合理,当然也有他的用法,体现在这里**


例:



#include
using namespace std;
template<class T1,class T2,class T3=int>
T3 add(T1 x,T2 y)
{
return x+y;
}
int main()
{
cout<<add(2.1,2)<<endl;
cout<<add<>(2,2.1 )<<endl;
cout<<add<char,int>(‘a’,1)<<endl;
cout<<add(‘b’,2.1)<<endl;

return 0;

}


**注意返回值是T3,必须默认给T3类型,不然T3自己找不到类型。**


**如果不给默认类型,那么显示调用必须多给一个类型给T3。**


**例子:**



> 
> 
> ```
> #include <iostream>
> using namespace std;
> template<class T1,class T2,class T3> 
> T3 add(T1 x,T2 y) 
> {
>     return x+y;
> }
> int main()
> {
>     cout<<add<char,int,int>('a',1)<<endl;
>     
>     
>     return 0;
> }
> ```
> 
> 


**当然模板的作用不只是俩个值相加,我们再来看看别的用法。**


**例设计一个通用函数,函数功能,就是为指针开辟堆区空间,空间大小由使用函数时决定。**


**例子**



#include
#include <assert.h>
#define max 6
using namespace std;

/*
template //模板一
T* newPoint(T ** p,int m)
{
*p=new T[m];
assert(NULL!=*p);
return *p;
}
/
template<class T,int m>//非类型模板形参:int m,用来替换函数模板中的常量值 T:类型模板型参,替换数据类型 m:非类型模板型参,替换常量值
T * newPoint()
{
T
p=new T[m];
assert(NULL!=p);
return p;
}
int main()
{
char *p=nullptr;
//newPoint(&p,max);
//newPoint(&p,max);
p=newPoint<char,max>(); //调用的是第二个函数模板,元素个数由模板形参列表中 决定
for(int i=0;i<max;i++)
{
cin>>p[i];
}
for(int i=0;i<max;i++)
{
cout<<p[i]<<" ";
}
cout<<endl;
return 0;
}


tips:


![](https://img-blog.csdnimg.cn/9a0e631d9e35457383141bb4993f15ed.png)


**类class模板**


1.如果一个类成为了模板那么这个类中所有成员函数将自动变成函数模板


类模板函数在内部实现



#include
using namespace std;
template
class demo//声明定义一个类模板
{
public:
demo(T x):x(x){}
void setvalue(T x)
{
this->x= x;
}
T getvalue()
{
return x;
}
private:
T x;
};
int main()
{
demo obj(123);
obj.setvalue(45);
cout<<obj.getvalue()<<endl;
return 0;
}


类模板函数在外部实现




#include
using namespace std;
template
class demo//声明定义一个类模板
{
public:
/*
demo(T x):x(x){}
void setvalue(T x)
{
this->x= x;
}
T getvalue()
{
return x;
}
*/
demo(T x);
void setvalue(T x);
T getvalue();
private:
T x;
};
template
demo::demo(A x):x(x){}
template
void demo::setvalue(B X)
{
this->x=X;
}
template
C demo::getvalue()
{
return x;
}
int main()
{
demo obj(23); //类模板定义对象时,必须显示说明使用的类模板<>,并且必须传递数据类型
obj.setvalue(45);
cout<<obj.getvalue()<<endl;
return 0;
}


类的非类型模板参数



#include
using namespace std;
template<class T,int max>
class demo
{

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐