news 2026/6/10 12:38:52

C++之函数模板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++之函数模板

文章目录

  • 函数模板的定义
  • 函数模板的实例化
  • 模板参数
    • 模板参数的匹配问题
      • 解决参数的匹配问题的方法
    • 模板函数的形参表
  • 函数模板的特化
  • 函数模板提供了一种通用的函数行为,该函数行为可以用多种不同的数据类型进行调用,编译器会根据调用类型自动将它实例化为具体数据类型的函数代码,也就是说函数模板代表了一个函数家族。与普通函数相比,函数模板中某些函数元素的数据类型是未确定的,这些元素的类型将在使用时被参数化;与重载函数相比,函数模板不需要程序员重复编写函数代码,它可以自动生成许多功能相同但参数和返回值类型不同的函数

函数模板的定义

template<typenameT1,typenameT2,....>返回类型 函数名(参数表){......}
  • template是模板定义的关键字; 写在<>中的T1 T2,…是模板参数,其中的typename表示其后的参数可以是任意类型的
#include<iostream>usingnamespacestd;#if0intMin(inta,intb){returna<b?a:b;}floatMin(floata,floatb){returna<b?a:b;}doubleMin(doublea,doubleb){returna<b?a:b;}charMin(chara,charb){returna<b?a:b;}#endiftemplate<typenameT>TMin(T a,T b){returna<b?a:b;}intmain(void){intm=9,n=3;doubled1=1.8,d2=3.4;cout<<Min(m,n)<<endl;cout<<Min(d1,d2)<<endl;return0;}

函数模板的实例化

  • 当编译器遇到关键字template和跟随其后的参数定义时,它只是简单地知道这个函数模板在后面的程序代码中可能会用到。除此之外,编译器并不会做额外的工作。在这个阶段函数模板本身并不能使编译器产生任何代码,因为编译器此时并不知道函数模板要处理的具体数据类型,根本无法生成任何函数代码
  • 当编译器遇到程序中对函数模板的调用时,它才会根据调用语句中实参的具体类型,确定模板参数的数据类型,并用此类型替换函数模板的模板参数,生成能够处理该类型的函数代码,即模板函数
  • 可以执行以下命令观察
nm a.out|grepa.out

模板参数

模板参数的匹配问题

  • C++在实例化函数模板的过程中,只是简单地将模板参数替换为实参的类型,并以此生成模板函数,不会进行参数类型的任何转换。这种方式与普通函数的参数处理有着极大的区别,以前在普通函数的调用过程中,会进行参数的自动类型转换
  • 以上程序能够正确执行。现在使用函数模板来实现通用的功能,如下所示
#include<iostream>usingnamespacestd;template<typenameT>TMax(T a,T b){returna>b?a:b;}intmain(void){doublea=2,b=3.4;floatc=1.1,d=2.2;cout<<"2, 3.4 的最大值是: "<<Max(a,b)<<endl;cout<<"a, c的最大值是: "<<Max(a,c)<<endl;cout<<"a, 100的最大值是: "<<Max(a,100)<<endl;return0;}
  • 编译以上程序,产生模板参数不匹配的错误。产生这个错误的原因是模板实例化过程中不会进行任何的参数类型转换。编译器在翻译Max(a,c)时,由于实参类型为double和float,而Max函数模板只有一个形参类型T,总不能让T同时取double和float两种类型吧?要知道模板实例化过程中,C++不会进行任何形式的隐式类型转换,于是产生了上述编译错误

解决参数的匹配问题的方法

  • 在模板调用时进行参数类型的强制转换
cout<<"a, c的最大值是: "<<Max(a,double(c))<<endl;
  • 显示指定函数模板实例化的类型参数
#include<iostream>usingnamespacestd;template<typenameT>TMax(T a,T b){returna>b?a:b;}intmain(void){doublea=2,b=3.4;floatc=1.1,d=2.2;cout<<"2, 3.4 的最大值是: "<<Max(a,b)<<endl;cout<<"a, c的最大值是: "<<Max<double>(a,c)<<endl;cout<<"a, 100的最大值是: "<<Max<double>(a,100)<<end;return0;}
  • 指定多个模板参数
    • 在模板函数的调用过程中,为了避免出现一个模板参数与多个调用实参的类型冲突问题,可以为函数模板指定多个不同的类型参数
#include<iostream>usingnamespacestd;template<typenameT1,typenameT2>T1Max(T1 a,T2 b){returna>b?a:b;}intmain(void){doublea=2,b=3.4;floatc=1.1,d=2.2;cout<<"2, 3.4 的最大值是: "<<Max(a,b)<<endl;cout<<"a, c的最大值是: "<<Max(a,c)<<endl;cout<<"a, 100的最大值是: "<<Max(a,100)<<endl;return0;}

模板函数的形参表

  • 不要误以为函数模板中的参数只能是类型形参,它也可以包括普通类型的参数
#include<iostream>usingnamespacestd;// 函数模板:包含类型形参 T + 普通类型参数 n(数组长度)template<typenameT>voiddisplay(T&arr,unsignedintn){for(inti=0;i<n;i++){cout<<arr[i]<<"\t";}cout<<endl;}intmain(void){inta[]={12,34,56,78,11,10,999};charb[]={'x','y','z','n'};display(a,sizeof(a)/sizeof(a[0]));display(b,sizeof(b)/sizeof(b[0]));return0;}

函数模板的特化

  • 在某些情况下,函数模板并不能生成处理特定数据类型的模板函数。上面例子中的Max函数模板可以计算int 或者 char类型数据的最大值,但对于字符串类型却是无能为力的
  • 解决这类问题的方法就是对函数模板进行特化。所谓特化,就是针对模板不能处理的特殊数据类型,编写与模板同名的特殊函数专门处理这些数据类型。语法格式如下所示
template<>返回类型 函数名<特化的数据类型>(参数表){....}
#include<iostream>#include<cstring>usingnamespacestd;template<typenameT>TMin(T a,T b){returna<b?a:b;}template<>constchar*Min(constchar*a,constchar*b){cout<<"Min(const char *, const char *)"<<endl;return(strcmp(a,b)>0)?b:a;}intmain(void){intm=9,n=3;doubled1=1.8,d2=3.4;cout<<Min(m,n)<<endl;cout<<Min(d1,d2)<<endl;cout<<Min('a','b')<<endl;cout<<Min("aaa","bbb")<<endl;return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 11:54:11

【UMEP第12.3期】LQF实例教程:模拟伦敦2015年人类活动热通量QF

目录Initial Practical stepsLQF 教程 1&#xff1a;简单的人类活动热流&#xff08;QF&#xff09;建模准备数据&#xff08;Preparing data&#xff09;一、准备输入数据二、配置 shapefile&#xff08;人口与输出区域&#xff09;三、验证人口属性字段四、建模所需的 NML 配…

作者头像 李华
网站建设 2026/6/9 0:53:05

Flask-Caching深度详解

1. 他是什么Flask-Caching 是 Flask 框架的一个扩展包。你可以把它理解为给 Flask 应用配备的一个“快速存取仓库”。Flask 本身没有自带缓存功能。当应用收到请求时&#xff0c;即使请求的是完全相同的数据&#xff0c;每次都得把数据库翻一遍&#xff0c;或者把复杂的计算重来…

作者头像 李华
网站建设 2026/6/10 12:39:51

Java后端开发者必看:收藏这份120天转型大模型工程师的魔鬼训练路线图【后端开发转行大模型应用开发】

本文针对Java后端开发者&#xff0c;揭示了从传统后端到AI大模型工程师的转型路径。文章对比了传统后端与大模型工程师的薪资差距&#xff0c;强调了后端开发者转型大模型的优势&#xff0c;包括分布式系统理解、工程化能力、架构设计思维等。同时&#xff0c;提供了详细的120天…

作者头像 李华
网站建设 2026/6/10 12:36:52

RavenDB Enterprise 7.2.0

RavenDB Enterprise是一款高性能 NoSQL OLTP 文档数据库&#xff0c;以其简洁性、集群功能和强大的特性而著称。跨多个节点的实时复制确保了数据安全性和持续可用性。它支持高达每秒 15 万次的写入和超过 100 万次的读取&#xff0c;是 Windows、Linux、macOS 和 Docker 等平台…

作者头像 李华
网站建设 2026/6/10 12:39:11

如何防御你的 RAG 系统免受上下文投毒攻击

作者&#xff1a;来自 Elastic Toms Mura 上下文工程技术如何防止 LLM 响应中的上下文投毒。 Agent Builder 现在已经正式发布。你可以通过 Elastic Cloud Trial 开始使用&#xff0c;并在这里查看 Agent Builder 的文档。 随着 Claude Sonnet 4.5、Gemini 3 系列 和 GPT 5 等模…

作者头像 李华
网站建设 2026/5/29 3:35:18

AI系统安全加固方案:架构师如何设计安全的密钥管理系统

AI系统安全加固方案&#xff1a;架构师如何设计安全的密钥管理系统 一、引言&#xff1a;AI时代&#xff0c;密钥管理为什么是“生命线”&#xff1f; 2023年&#xff0c;某头部AI公司发生了一起API密钥泄露事件&#xff1a;一名工程师将包含LLM推理API密钥的配置文件误推到公共…

作者头像 李华