【c++】模板和模板类

C++是一种“强类型”语言。也就是说,对于一个变量,编译器必须确切知道它是什么类型。但是,这种强类型函数在实现一些简单函数反而更麻烦。例如:求两大数的较大者,应以Max( )函数,我们需要对不同数据类型分别定义不同重载版本来实现:

int Max(int x,int y)        //比较两个int类型的值
{
    return ((x > y) ? x : y);
}
float Max(float x,float y)  //比较两个float类型的值
{
    return ((x > y) ? x : y);
}
double Max(double x,double y)  //比较两个double类型的值
{
    return ((x > y) ? x : y);
}

我们看到,虽然我们可以通过函数重载去实现,但明显存在一些缺点:
1、所有的函数除返回类型外,函数体都相同,代码复用率低;
2、只要新类型出现,我们就需要添加新的对应函数;
3、维护不方便。

什么是模板?
C++程序有类和函数组成,模板分为类模板和函数模板。模板就是把功能相似,仅数据类型不同的函数或类设计为通用的函数模板或类模板,提供给用户。
模板是“泛型编程”的基础。简单的说,类是对象的抽象,而模板是类的抽象,用模板能定义具体类。
函数模板的一般定义形式:

template<typename Paraml,typename Paraml,... ,class Paraml>
返回类型 函数名(函数形参表)
{
}

模板定义以关键字template开始,形参由关键字class或typename及其后面的类型名构成,一般建议尽量使用typename。
注意:不能使用struct代替typename。
模板函数也可以定义为inline函数

template<typename T> 
inline T Add(const T _left, const T _right) 
{ 
return (_le _right); 
} 

注意:inline关键字必须放在模板形参表之后,返回值之前,不能放在template之前
例如:前面的Max()函数可以用模板定义如下:

template<typename T> 
T Max(T x,T y)
{
   return ((x > y) ? x : y);
}

模板是一个蓝图,它本身不是类也不是函数,编译器用模板产生的指定的类或者函数的特定类型版本,产生模板特定类型的过程称为函数模板实例化。
实例:定义一个函数模板,比较两个数大小。

#include<iostream>
using namespace std;
template<typename T>
T Max(T x, T y)
{
    return ((x > y) ? x : y);
}
int main()
{
    cout << Max(10, 20) << endl;
    cout << Max(13.14, 5.2) << endl;
    cout << Max(10, (int)5.2) << endl;
    cout << Max<int>(10, 5.2) << endl;

}

模板参数 :1,类型参数
2,非类型参数
类型参数可以用来指定返回类型或函数的参数类型,以及在函数体内用于变量的声明或类型的转换:

template<typename T>
T foo(T* p)
{
   T tmp = *p;
   return tmp;
}

模板形参的名字在同一模板形参列表中只能使用一次。

非类型模板参数 :
一个非类型参数表示一个值而非一个类型。非模板类型形参是模板内部定义的常量,在需要常量表达式的时候,可以使用非模板类型参数。
例如数组长度:
这里写图片描述说明:
1、一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例
化为这个非模板函数。
2、对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调动非模板
函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,
那么将选择模板。
3、显式指定一个空的模板实参列表,该语法告诉编译器只有模板才能来匹配这个调用,
而且所有的模板参数都应该根据实参演绎出来。
4、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。
模板函数特化
特化的一般形式:
1、关键字template后面接一对空的尖括号<>
2、函数名后接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参
3、函数形参表
4、函数体
例如,对于前面的Max()函数模板。

template<class T>
T Max(T x,T y)
{
   return ((x>y) ? x:y);
}

如果比较的是两个“const char*”类型,那么函数模板用“const char*”型的模板实参实例化。如果还想让每个实参都被解释为C风格的字符串而不是字符指针,那么饿通过模板定义给出的语义就不正确了,必须为函数模板实例化提供“const char*”的特化:

#include<cstring>     //引入cstring的相关声明
template<>           //特化标志
const char* Max<const char*>(const char* x,const char* y)            //用const char*转化
{
    return (strcmp(x,y)<0)?x:y;
}

特化的声明必须与特定的模板相匹配。
由于有了这个特化,程序中对所有用两个“const char*”型形参进行调用的Max()都会调用这个特化的定义,而对于其他的调用,则通过模板定义实例化对象:

const char* a = “hello”;
const char* b = "world";
int x = 10;
int y = 20;
Max(a,b);      //调用模板的特化版本进行实例化
Max(x,y);      //调用模板的通用版本进行实例化  

注意:在模板特化版本的调用中,实参类型必须与特化版本函数的形参类型完全匹配,如果不匹配,编译器将为实参模板定义中实例化一个实例。

这里写图片描述

版权声明:本文为prefect_boy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/prefect_boy/article/details/71194967

智能推荐

Intellij IDEA 搭建Spring Boot项目(一)

Intellij IDEA 搭建Spring Boot项目 标签(空格分隔): SpringBoot JAVA后台 第一步 选择File –> New –> Project –>Spring Initialer –> 点击Next  第二步 自己修改 Group 和 Artif...

CentOS学习之路1-wget下载安装配置

参考1: https://blog.csdn.net/zhaoyanjun6/article/details/79108129 参考2: http://www.souvc.com/?p=1569 CentOS学习之路1-wget下载安装配置 1.wget的安装与基本使用 安装wget yum 安装软件 默认安装保存在/var/cache/yum ,用于所有用户使用。 帮助命令 基本用法 例子:下载...

深入浅出Spring的IOC容器,对Spring的IOC容器源码进行深入理解

文章目录 DispatcherServlet整体继承图 入口:DispatcherServlet.init() HttpServletBean.init() FrameworkServlet.initServletBean() 首先大家,去看Spring的源码入口,第一个就是DispatcherServlet DispatcherServlet整体继承图 入口:DispatcherServlet....

laravel框架的课堂知识点概总

1. MVC 1.1 概念理解 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑 MVC 是一种使用 MVC(Model View Controller ...

Unity人物角色动画系统学习总结

使用动画系统控制人物行走、转向、翻墙、滑行、拾取木头 混合树用来混合多个动画 MatchTarget用来匹配翻墙贴合墙上的某一点,人物以此为支点翻墙跳跃 IK动画类似于MatchTarget,控制两只手上的两个点来指定手的旋转和位置,使得拾取木头时更逼真 创建AnimatorController: 首先创建一个混合树,然后双击 可以看到该混合树有五种状态机,分别是Idle、WalkForward、...

猜你喜欢

Composer 安装 ThinkPHP6 问题

Composer 安装 ThinkPHP6 问题 先说说问题 一.运行环境要求 二.配置 参考: ThinkPHP6.0完全开发手册 先说说问题 执行ThinkPHP6的安装命令 遇到问题汇总如下: 看提示是要更新版本,执行命令更新。 更新之后,再次安装ThinkPHP,之后遇到如下问题。 尝试了很多方法,依然不能解决。其中包括使用https://packagist.phpcomposer.com...

Spring Boot 整合JDBC

今天主要讲解一下SpringBoot如何整合JDBC,没啥理论好说的,直接上代码,看项目整体结构 看一下对应的pom.xml 定义User.java 定义数据源配置,这里使用druid,所以需要写一个配置类 上面指定druid的属性配置,和用户登录的账号信息以及对应的过滤规则: 下面定义数据访问接口和对应的实现: 数据访问层很简单,直接注入JdbcTemplate模板即可,下面再看对应的servi...

html鼠标悬停显示样式

1.显示小手:     在style中添加cursor:pointer 实现鼠标悬停变成小手样式     实例:         其他参数: cursor语法: cursor : auto | crosshair | default | hand | move | help | wait | tex...

Yupoo(又拍网)的系统架构

Yupoo!(又拍网) 是目前国内最大的图片服务提供商,整个网站构建于大量的开源软件之上。以下为其使用到的开源软件信息: 操作系统:CentOS、MacOSX、Ubuntu 服务器:Apache、Nginx、Squid 数据库:MySQLmochiweb、MySQLdb 服务器监控:Cacti、Nagios、 开发语言:PHP、Python、Erlang、Java、Lua 分布式计算:Hadoop...

创建一个Servlet项目流程(入门)

版本 IDEA 2020.2 JDK1.8 apache-tomcat-9.0.36 项目流程 一、IDEA中新建JaveEE项目 项目起名,选择项目存放地址,点击finish创建成功 进入项目后,右键选择项目,选择add Framework Support 选择Web Application,点击OK 此时项目文件夹 在WEB-INF下创建两个目录classes和lib 按ctrl+alt+sh...