首页 > 编程语言 >C++:18---函数模板(template)

C++:18---函数模板(template)

时间:2022-11-01 14:38:07浏览次数:52  
标签:const 函数 int 18 C++ --- return 模板 定义

一、模板的定义

  • template<typename T>
  • 以关键字template开头,后面跟一个模板参数列表,列表里面用逗号将多个模板参数隔开定义的注意事项

模板的编译

  • 当编译器遇到一个模板定义时,并不生成代码。只有当实例化处模板的一个特定版本时,编译器才会生成代码
  • 重点:通常,当我们调用一个函数/定义实例化一个类时,编译器只需掌握函数的声明/类的声明即可,因此可以把函数/类的声明放置在头文件,而把函数/类的定义放置在源文件中。但是模板则不同:为了实例化模板函数,编译器必须掌握函数模板/类模板成员函数的声明和定义,因此只能将模板函数/类的声明和定义都放置在头一个头文件/源文件中(重点)

二、函数模板与模板函数

  • 函数模板:一个模板(是模板)
  • 模板函数:调用函数模板时生成的函数(是函数),也称为函数模板的实例化

一个模板参数列表只和一个函数模板相对应。因此每定义一个函数模板就需要重新定义一个模板参数列表

//定义模板以及一个函数模板


template <typename T>
int compare(const T &v1, const T &v2);
int main()
{
compare(1, 2); //模板函数,也称为模板的实例化
compare("ABC","DEF");//模板函数
return 0;
}

三、模板类型参数

  • 模板参数列表不能为空
  • 模板参数既可以用typename声明,也可以使用class声明。不过建议前者
//定义模板以及一个函数模板


template <typename T, class U>
int compare(const T &v1, const U &v2);
int main()
{
compare(1, 1); //T为int,U也为int
compare(1,"DEF"); //T为int,U也为string
return 0;


}

四、非类型模板参数

  • 除了定义上面的模板类型参数,我们也可以定义非类型参数。
  • 一个非类型参数表示一个值而非一个类型。并且通过特定的类型名定义而非typename或class来定义
  • 当一个模板被实例化时,非类型参数被用户提供或者编译器推断的值所代替。
  • 重点:一个非类型参数可以是一个整型、一个指向对象或函数的指针(或引用)。且实参必须是一个常量表达式
  1. //定义模板以及一个函数模板。
  2. template <unsigned N, unsigned M>
  3. int compare(const char(&p1)[N], const char(&p2)[M])//传入数组的引用来比较数组大小
  4. {
  5. return strcmp(p1, p2);
  6. }
  7. int main()
  8. {
  9. compare("hi","mom");//编译器会使用字面值常量的大小来代替N和M
  10. return 0;
  11. }

五、inline、constexpr函数模板

  • 函数模板可以声明为inline或constexpr。但是这些关键字必须放在函数的返回值类型前面,模板参数列表的后面
  1. template<typename T> //正确
  2. inline T func(T const&);
  3. constexpr template<typename T> //错误,constexpr位置错误
  4. T func2(T const&);

六、定义类型无关的代码

  • 当我们定义函数模板时,如果函数能处理的功能只限于一些特定的情况,而不能作用于大多数的情况,那么这个函数模板的操作性与可移植性就比较差
  • 为了解决上面这个问题,我们在定义函数模板时,就需要考虑类型无关与可移植性

案例:

  •  下面这个函数模板如果调用它比较两个指针,而这两个指针未指向相同的数组,则代码的行为是未定义的
template <typename T>
int compare(const T& s1, const T& s2)
{
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}



  •  下面我们编写了这个函数模板,也可以用于传入指针也可以正常使用的函数模板(但是还不是最完美的,所以在定义时,要考虑各种因素而达到更高的标准)


1. template <typename T>
2. int compare(const T& s1, const T& s2)
3. {
4. if (less<T>()(v1,v2))
5. return -1;
6. if (less<T>()(v2, v1))
7. return 1;
8. return 0;
9. }


前方高能,我来出一个代码例子,来看看结果和你想的是否一致?

练习:

#include <iostream>
#include <cstring>
using namespace std;
template<typename T1,typename T2>
bool Compare(const T1& t1,const T2& t2)
{
cout << "call Compare(const T1& t1,const T2& t2)" << endl;
if(t1 > t2){
return true;
}
return false;
}
bool Compare(const char* s1,const char* s2)
{
cout << "call Compare(const char* s1,const char* s2)" << endl;
return strcmp(s1,s2);
}
bool Compare(const float& t1,const float& t2)
{
cout << "call Compare(const float& t1,const float& t2)" << endl;
if(t1 > t2){
return true;
}
return false;
}
int main(){
int a = 12,b=23;
Compare(a,b);
const char *p = "11111";
const char *q = "00";
Compare(p,q);


float c=12.0,d=15.7;
Compare(c,d);
return 0;
}

为什么结果是

call Compare(const T1& t1,const T2& t2)

call Compare(const char* s1,const char* s2)

call Compare(const float& t1,const float& t2)

呢?接下来就是我们下一节要讲的模板的特化。



标签:const,函数,int,18,C++,---,return,模板,定义
From: https://blog.51cto.com/u_14934686/5813606

相关文章

  • C:02---scanf、printf
    一、printf​控制符①精度控制:输入小数点后m位(%.mf)。右对齐5位,保留小数点后m位(%d.mf)%f、%lf默认输出6位小数②宽度:%md(打印m为,右对齐,多出m位照常打印)。%-md(打印m位,左对齐,多......
  • C++:17---sizeof运算符
    功能:以字节位单位,返回一个表达式或一个数据类型所占的字节数返回值类型:是size_t类型sizeof有无括号:sizeof不加括号,后面不可以直接跟数据类型sizeof加括号,后面既可以跟表达式......
  • Redis:10---List对象
    ​一、列表对象概述   列表类型是用来存储多个有序的字符串,一个列表最多可以存储多个元素。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有......
  • C++:44---关键字virtual、override、final
    一、虚函数概念:在函数前面加virtual,就是虚函数虚函数的一些概念:只有成员函数才可定义为虚函数,友元/全局/static/构造函数都不可以虚函数需要在函数名前加上关键字virtual成......
  • C++:45---多态
    一、多态介绍面向对象的核心思想是多态性,其含义是“多种形式”概念:在子类覆盖了父类函数的情况下,用父类的指针(或引用)调用子类对象,或者通过父类指针调用覆盖函数的时候(动......
  • C++(STL):26 ---关联式容器set用法
    set容器都会自行根据键的大小对存储的键值对进行排序,只不过set容器中各键值对的键key和值value是相等的,根据key排序,也就等价为根据value排序。另外,使用set容器......
  • 怎么查小河流名称--河流数据库
    全国最大的河流名称数据库,没有你找不到的当一条河流自上而下不同河段有不同的名称时,一般以下游的河名作为整个河流的名称。当河流在地形图上没有标注名称时,可采用下列方法......
  • C++(STL):06---数值的极值(numeric_limits类)
    一、数值的极值概述数值类型有着与平台相依的极值C++标准规定了各种类型必须保证的最小精度。这些最小值如下图所示: 类型最小长度char1byte(8bits)shortint2bytesint2bytes......
  • C++:51---继承中的构造函数、析构函数、拷贝控制一系列规则
    一、继承中的构造函数根据构造函数的执行流程我们知道:派生类定义时,先执行基类的构造函数,再执行派生类的构造函数拷贝构造函数与上面是相同的原理二、继承中的析构函数根据析......
  • C++:46---绝不重新定义继承而来的non-virtual函数
    一、看一个隐藏non-virtual函数的例子假设classD以public的方式继承于classB,代码如下:classB{public:voidmf();};classD:publicB{};intmain(){Dx;B*pB=&x;pB->......