C++模板使用
C++模板
模板是一种对类型进行参数化的工具;
通常有两种形式:函数模板和类模板;
函数模板针对仅参数类型不同的函数;
例如:Max函数 :求两个数的最大值,我们需要对各种数据类型进行重载,如下
int Max(int a,int b)
{
return (a>b?a:b);
}
double Max(double a,double b)
{
return (a>b?a:b);
}
但如果在主函数中,我们分别定义了 char a,b; 那么在执行max(a,b);时 程序就会出错,因为我们没有定义char类型的重载版本。
此时可以采用函数模板:
template <class T>
T Max(T a,T b)
{
return (a>b?a:b);
}
函数运行结果:
int _tmain(int argc, _TCHAR* argv[])
{
cout<<Max('a','b');
getchar();
return 0;
}
类模板针对仅数据成员和成员函数类型不同的类。
模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。
下面进入正题:
模板使用
函数模板使用
模板定义以关键字templeate开始,后接模板形参表,模板形参表是用尖括号括住的一个或多个模板形参的列表,形参之间以逗号分隔
例如 :(在这里 typename和class没有什么区别)
template <typename T>
int compare(const T& v1,const T& v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0;
}
针对inline函数也存在inline函数模板
template <typename T> inline T min(const T&,const T&);
以下代码错误:
inline template<typename T> T min(const T&,const T&);
inline关键字必须在template之后
即:说明符放在模板形参列表之后,返回类型之前,不能放在关键字template之前
模板实参省略问题:
以下四种情况模板实参不能省略
- 从模板函数实参表获得的信息有矛盾
例如:
template <typename T>
T add(const T& a,const T& b)
{
return (a+b);
}
调用如下:
int _tmain(int argc, _TCHAR* argv[])
{
cout<<add<int>(1,2.1)<<endl;
getchar();
return 0;
}
add两个参数:一个是1(int),一个是2.1(double),两个参数类型不一致,调用时必须指定一个类型,否则编译器报错
运行结果:
2. 虚拟类型参数没有出现在模板函数的形参表中
例如:
template <typename T1,typename T2,typename T3>
T2 minus(const T1& a,const T3& b)
{
return (a-b);
}
调用如下:
int _tmain(int argc, _TCHAR* argv[])
{
cout<<minus<int,double,long>(2,3)<<endl;
getchar();
return 0;
}
T1,T3出现在形参列表,而T2没有出现在形参之中。所以必须指定T2的类型,以上调用如果写成“minus<int,int>(2,3)”,编译器也不会报错,只要指定了T2,编译器就不会报错
运行结果:
3. 需要获得特定类型的返回值,而不管参数的类型如何
例如:add<int>(a,b);
4. 函数模板含有常规形参,且常规参数的信息无法从模板函数的实参表中获得
例如:
template<class T,int nums>
void sum(T data[],T& result)
{
result = 0;
for(int i=0;i<nums;i++)
{
result += data[i];
}
}
调用如下:
int _tmain(int argc, _TCHAR* argv[])
{
int d[3] = {1,2,3};
int res;
sum<int,3>(d,res);
cout<<res<<endl;
getchar();
return 0;
}
函数模板 sum 中,nums是常规参数,nums信息无法从实参列表中获取,所以必须制定常规参数的值
运行结果:
类模板使用
类模板和函数模板都是以template开始后接模板形参列表组成,模板形参不能为空,
一但声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,
即可以在类中使用内置类型的地方都 可以使用模板形参名来声明。比如
template<class T> class A{public: T a; T b; T hy(T c, T &d);};
类模板对象的创建:比如一个模板类A,则使用类模板创建对象的方法为A<int> m;在类A后面跟上一个<>尖括号并在里面填上相应的类型,这样的话类A中凡是用到模板形参的地方都会被int 所代替。
当类模板有两个模板形参时创建对象的方法为A<int, double> m;类型之间用逗号隔开。
对于类模板,模板形参的类型必须在类名后的尖括号中明确指定:比如A<2> m;用这种方法把模板形参设置为int是错误的(编译错误:error C2079: 'a' uses undefined class 'A<int>'),
类模板形参不存在实参推演的问题。也就是说不能把整型值2推演为int 型传递给模板形参。要把类模板形参调置为int 型必须这样指定A<int> m。
在类模板外部定义成员函数的方法为:
template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体},
比如有两个模板形参T1,T2的类A中含有一个void h()函数,则定义该函数的语法为:
template<class T1,class T2> void A<T1,T2>::h(){}。
注意:当在类外面定义类的成员时template后面的模板形参应与要定义的类的模板形参一致。
注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。
C++模板使用的更多相关文章
- Jade模板引擎让你飞
写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- CMS模板应用调研问卷
截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
- OpenCV模板匹配算法详解
1 理论介绍 模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标.OpenCV ...
- 前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定
一.前端MVC概要 1.1.库与框架的区别 框架是一个软件的半成品,在全局范围内给了大的约束.库是工具,在单点上给我们提供功能.框架是依赖库的.AngularJS是框架而jQuery则是库. 1.2. ...
- ThinkPHP+Smarty模板中截取包含中英文混合的字符串乱码的解决方案
好几天没写博客了,其实有好多需要总结的,因为最近一直在忙着做项目,但是困惑了几天的Smarty模板中截取包含中英文混合的字符串乱码的问题,终于解决了,所以记录下来,需要的朋友看一下: 出现乱码的原因: ...
- ThinkPHP 模板substr的截取字符串函数
ThinkPHP 模板substr的截取字符串函数在Common/function.php加上以下代码 /** ** 截取中文字符串 **/ function msubstr($str, $start ...
- DDD领域驱动设计 - 设计文档模板
设计文档模板: 系统背景和定位 业务需求描述 系统用例图 关键业务流程图 领域语言整理,主要是整理领域中的各种术语的定义,名词解释 领域划分(分析出子域.核心域.支撑域) 每个子域的领域模型设计(实体 ...
随机推荐
- 数据结构与算法(python版)
ADT抽象数据类型(ADT:Abstract Data Type):ADT是对数据进行处理的一种逻辑描述,并不涉及如何实现这些处理. 同一ADT可以采用不同的数据结构来实现:1.采用程序设计语言的控制 ...
- python序列化proto时对repeated修饰数据进行赋值(常用类型和其他类型)
说一下对proto文件中数据使用时的书写方法,因为笔者也经常弄混淆 一.repeated修饰符,该列表是常用类型,比如int message C2GS_GoodsList { repeated int ...
- Git常用命令和基础使用
Git 参考:廖雪峰的Git教程 Git 常用命令 git config --global user.name "name" #配置git使用用户 git config --glo ...
- 几张图搞懂 NodeJS 的流
假设我们现在要盖一座房子,我们买了一些砖块,厂家正在送货.现在我们有两个选择,一是等所有砖块都到了以后再开始动工:二是到一批砖块就开始动工,砖块到多少我们就用多少. 这两种方式哪种效率更高呢?显然是第 ...
- 利用共享内存实现比NCCL更快的集合通信
作者:曹彬 | 旷视 MegEngine 架构师 简介 从 2080Ti 这一代显卡开始,所有的民用游戏卡都取消了 P2P copy,导致训练速度显著的变慢.针对这种情况下的单机多卡训练,MegEng ...
- TCP拥塞控制详解
1. 拥塞原因与代价 拥塞的代价 当分组的到达速率接近链路容量时,分组经历巨大的排队时延. 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组. 发送方在遇到大时延时进行的不必要重传会引起路由器利用其链 ...
- WPF(MVVM) 利用资源字典实现中英文动态切换
1.首先新建两个字典文件en-us.xaml.zh-cn.xaml.定义中英文的字符串在这里面. 2.将两个资源字典添加到App.xaml中,这里注意下,因为两个字典中有同样字符,如果没有动态更改,默 ...
- centos7上用docker搭建简单的前后端分离项目
1. 安装docker Docker 要求 CentOS 系统的内核版本高于 3.10 ,首先验证你的CentOS 版本是否支持 Docker . 通过 uname -r 命令查看你当前的内核版本 使 ...
- 通过Mssql提权的几种姿势
本文记录针对SQL Server数据库,在拿到shell之后进行提权的5种方法. 一. xp_cmdshell提权 上面的数据库连接需要知道sa的密码,连接之后,在下面的sql命令处执行: exec ...
- Element Vue 开箱即用框架如何使用-测试开发【提测平台】阶段小结(二)
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 上一篇总结了后端服务接口的开发,这篇我们主要来总结下前后端分离开发中的前端部分,主要是开箱即用的框架介绍和之前章节组件的梳理和部分的扩展内 ...