函数模板是通用的函数描述,其使用泛型来定义函数。其实就是有些操作,如果撇开具体的变量的数据类型,其操作是一样的如果我们将这些操作写成一个模板,在调用不同变量的时候就设定好变量类型就可了,后续的操作基本都是一个流程了。

比如我要对两个变量进行交换,那么不管是int型、double型还是long型或者类或者结构体啥的,我都可以这样实现:

T A = AAAAA;
T B = SB;
T temp = A;
A = B;
B = tem;

这里的T就是数据类型的,不管是什么数据类型,只要可以进行如上操作的,都可以用这个模板来做。

1、函数模板定义

函数模板的定义基本上固定的:

template <typename T>    
void aiZuoNiNa(T a)
{
    
}

其中,template是函数模板的关键字,关键字typename是声明该函数模板的泛型类型,可以用class来替代(C++98前没有typename,所以用class),这两个关键字和尖括号是必须的,typename之后的T可以任意写,只要符合C++命名规则即可,很多人会写做T。

需要注意的是,在定义函数模板的时候是不会创建任何函数的,只是在告诉编译器在调用模板函数的时候该如何定义函数并调用,也就是说如果定义了模板函数,但是从未调用过的话,是不会生成相应的函数的,在程序中使用了定义好的函数模板,那么编译器将检查使用的参数类型,然后根据类型来生成相应函数(就如同我们手写了一个函数一样)。所以即使定义函数模板只有一份,如果调用了两次且数据变量不同的话,编译器会生成两份独立的函数在可执行程序中,也就是说函数模板不会缩短可执行程序,最终的可执行程序也不会包含函数模板,但是会包含调用两次函数模板后编译器所生成的两个独立的函数。

函数模板一般是放在头文件中的。

并不是模板函数的所有参数都得是泛型,可以不要泛型,或者包含其它类型:

template <typename T>
void aiZuoNiNa(T a)
{ } template <typename T>
void aiZuoNiNa(T a, int b)
{ } template <typename T>
void aiZuoNiNa()
{ }

2、模板重载

上面一个例子涉及到函数模板的重载,函数模板的重载与普通函数重载一样,重载函数模板的时候,需要满足函数名相同、参数列表不同函数重载特点即可。

3、函数模板的局限性

这个要怎么说呢,应该说是某些情况不适合简单抽象化或者简单模板化,才导致了函数模板的局限性,比如比较两个变量的大小,对于int、float等数据类型可以实现模板化,但是如果是一个结构体或者一个类、或者一个数组等,在不重载比较操作符号(<、>、==)的时候显然不能这样比较吧。

4、显式具体化

因为有些情况可能不能直接简单的用函数模板,所以才会提供一个具体化函数定义(称为显式具体化,explicit specialization),其中包含所需要的代码,在编译器找到与调用函数匹配的具体化定义后就不再寻找模板函数了。也就是显示具体化函数优先级大于函数模板。C++98的具体化方法规定:

1、对于给定的函数名,可以有非模板函数、模板函数、显示具体化模板函数以及它们的重载;

2、显式具体化的原型和定义应以template<>开头,并通过名称来指定类型;

3、具体化优先于常规模板,而非模板函数优先于具体化和常规模板。

第一条有重载的意味,第二条指出显示具体化的格式,第三条指出当存在多个函数的时候,编译器寻找顺序是非模板函数>具体化模板函数>模板函数。在调用模板函数指定数据类型的时候编译器是会生成一个对应的函数实例,这个函数是不在代码中可见的,故而这种实例化是隐式的,而显示具体化则是在代码里定义的:

// 函数模板
template <typename T>
void jiaoJiRen(T a, T b)
{ }
//显式具体化
template<> void jiaoJiRen<char>(char a, char b)
{ }

5、实例化和具体化

一开始是只有隐式实例化,显示实例化是现在的C++才有的,显式实例化需要声明所需的数据类型(用<>指示数据类型),并在声明前面添加关键字template:

template void jiaoJiRen(int a, int b);

显式具体化是要求编译器在调用的时候不要按照函数模板中的方式来生成函数定义,而要用显式具体化的函数:

//方式一
template<> void jiaoJiRen<char>(char a, char b)
{ }
//方式二
template<> void jiaoJiRen(char a, char b)
{ }

显式具体化和显式实例化的区别:

1、具体化函数声明前

2、显式具体化除了声明还有函数定义,显式实例化只需要做函数声明即可。

3、在同个文件(或者转换单元)中使用同一种类型的显示实例化和显式具体化会出错。

函数模板这一块大致就记录这一些,我觉得暂时够用即可,毕竟是一个工具,目前就是挖的很深,没有使用的余地的话,很快就遗忘,个人的一点感受,之前看设计模式的时候觉得都记住了,一段时间后都模糊了,然后自己昨天写完一个小软件的时候才意识到自己其实用到了单例模式,再去查下单例模式,才知道我用的这个叫懒汉方式。所以有点感想,对于工具的一种学习方法是在实践中使用它,故而有句很装逼的话:

无他,但手熟尔。

C++基础--函数模板的更多相关文章

  1. C++进阶-1-模板基础(函数模板、类模板)

    C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...

  2. Template 基础篇-函数模板(待看

    Template 基础篇-函数模板 Template所代表的泛型编程是C++语言中的重要的组成部分,我将通过几篇blog对这半年以来的学习做一个系统的总结,本文是基础篇的第一部分. Template ...

  3. C++ 函数模板基础知识

    为什么要引入模板:为了避免代码重复,程序员可以编写脱离数据类型通用模板. 模板的分类:函数模板 + 类模板 注意:模板的声明或定义只能在全局,命名空间或类范围内进行.不能在函数内进行,比如不能在mai ...

  4. [C++基础]那些容易被混淆的概念:函数/数组指针-指针函数/数组,类/函数模板-模板类/函数

    函数指针-指针函数 函数指针的重点是指针.表示的是一个指针,它指向的是一个函数.eg: int (*pf)(); 指针函数的重点是函数.表示的是一个函数,它的返回值是指针.eg: int* fun() ...

  5. 【C++编程基础】(1)—— 函数原型声明、函数模板、引用、const 常引用、const 常量指针

    一.函数原型声明: 1.函数声明告诉编译器函数的名称,和如何调用函数(返回类型和参数):函数定义提供了函数的实际主体. 2.强制性的:在C++中,如果函数调用的位置在函数定义之前,则要求在函数调用之前 ...

  6. 读书笔记_Effective_C++_条款四十五:运用成员函数模板接受所有兼容类型

    比如有一个Base类和一个Derived类,像下面这样: class BaseClass {…}; class DerivedClass : public BaseClass {…}; 因为是父类与子 ...

  7. [Reprint] C++函数模板与类模板实例解析

    这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下   本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...

  8. c++函数模板---3

    原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ 模板从大体上,可以分为两种:函数模板和类模板.函数模板是算法库的基础,类模板是建立标准库容器和迭代器的基 ...

  9. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

随机推荐

  1. Python基础_ONLINE习题集_03 数据类型

    3.1 将元组(1,2,3) 和集合{"four",5,6}合成一个列表 tuple,set,list = (1,2,3),{"four",5,6},[] fo ...

  2. NPOI,导出Execl,压缩文件zip,发送Email

    private void SendEmail(string emailAddress, string companyName,string proxy, string officer, DataTab ...

  3. php 打印格式化显示利器 <pre>

    当我们PHP调试的时候,用var_dump 或 print_r打印json数据或array数组时,html页面没有换行显示,看到的内容一大堆,不好定位. 输出前添加 <pre>,便可以自动 ...

  4. Codeforces #536 A..D 题解

    foreword ummm... 开始前几个小时被朋友拉来打了这一场,总体海星,题目体验极佳,很符合口味,稍微有点点简单了不知道是不是因为是 New Year Round,很快就打到了 D,但是题目阅 ...

  5. 收藏了一篇很有用的博客 “npm的安装教程”

    暂时贴上这一篇博客的地址,感谢原作者 https://www.cnblogs.com/goldlong/p/8027997.html 使用之前,我们先来掌握3个东西是用来干什么的. npm: Node ...

  6. python中软件开发规范,模块,序列化随笔

    1.软件开发规范 首先: 当代码都存放在一个py文件中时会导致 1.不便于管理,修改,增加 2.可读性差 3.加载速度慢 划分文件1.启动文件(启动接口)--starts文件放bin文件里2.公共文件 ...

  7. springCloud 之 Eureka服务治理

    服务治理是微服务架构中最核心和基础的模块 首先我们创建一个springCloud eureka service的springboot 工程,该工程提供一个服务中心,用来注册服务,第二个工程是clien ...

  8. C++面试常见问题——14内存管理

    内存管理 内存管理由三种方式: 自动存储 静态存储 动态存储 自动存储 对于函数的形参.函数内部变量.和结构体变量等,编译器在函数运行过程中在栈中自动对其分配内存,调用结束后对其进行销毁.变量的声明周 ...

  9. 【pwnable.kr】 [simple login]

    Download : http://pwnable.kr/bin/login Running at : nc pwnable.kr 9003 先看看ida里面的逻辑. 比较重要的信息时input变量再 ...

  10. ip 在网络传输中是如何传递的

    前言 ip 我们知道有ip4与ip6.ip6还未实行,那么就暂且不谈. ip4我们在传递的时候一般是这样的"127.0.0.1",但是我们传输的是信号,也就是二进制数据,这个字符如 ...