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

比如我要对两个变量进行交换,那么不管是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. ng -----监听变化($scope.$watch())

    需求:项目组件中遇到改变日期触发方法. 困难:日期组件中不涉及释焦功能 解决:在angularjs中用$scope.$watch() 其中name是字符串,是指监听到的具体对象值.

  2. Python 绘图

    python绘图库有很多,底层的就是matplotlib,另外还有基于matplotlib的更方便,代码可读性更强的库,比如seaborn.plotnine等.各个库之间的对比: https://ww ...

  3. clientDataSet转换sql

    ReadMe 新版本delphi,可以用string类型,旧版本需要用widestring =========================================== function T ...

  4. arm linux 移植支持 HP打印机

    背景 由于业务需要,需要hi3531d主板上加入对于HP打印机的支持. 通过与产品经理,技术主管的沟通:通用支持是不现实的,只要求彩色打印,先不考虑打印机的价格,只要支持一款打印机即可. 注意: Li ...

  5. 查看 Secret【转】

    可以通过 kubectl get secret 查看存在的 secret. 显示有两个数据条目,kubectl describe secret 查看条目的 Key: 如果还想查看 Value,可以用  ...

  6. 编程练习:求某个数的n次方,返回其个位和十位

    #!/usr/bin/env python def pow1(n,m): if m==0: return 1 if m==-1: return (1/n) if m & 1 != 0: ret ...

  7. 浅谈MSF渗透测试

    在渗透过程中,MSF漏洞利用神器是不可或缺的.更何况它是一个免费的.可下载的框架,通过它可以很容易地获取.开发并对计算机软件漏洞实施攻击.它本身附带数百个已知软件漏洞的专业级漏洞攻击工具.是信息收集. ...

  8. 剑指offer第12题打印从1到n位数以及大整数加法乘法

       字符和数字加减就是字符的ASCII码和数字直接加减. 方法一: 1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了:如果确实是最后 ...

  9. PHP时间格式

    date 用法: date(格式,[时间]); 如果没有时间参数,则使用当前时间.格式是一个字符串,其中以下字符有特殊意义: Y - 年,四位数字; 如: "1999" y - 年 ...

  10. 请求接口得到一段markdowm遇到的问题

    如图,在console里看得到这段数据 有<br>之类的东东,但是我们用部分富文本解析工具可能会显示不了回车,所以我们可以自己动手: 主要就是利用js的replace方法来把<br& ...