码迷,mamicode.com
首页 > 编程语言 > 详细

c++模板函数

时间:2018-04-06 23:44:38      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:目的   链接   function   error   简单的   理解   body   找不到   声明   

模板特化(也有翻译为模板具体化)(specialization)

??如果把模板函数当作数学归纳法的话,模板特化就是n=常数C的情况。

//模板函数声明
template <typename T>
bool greater(const T &a,const T &b);
int main()
{
    return 0;
}
//模板函数定义
template <typename T>
bool greater(const T &a,const T &b)
{
    if(a > b)
        return true;
    else
        return false;
}

??如果上面的T是char*类型,那么这种比较是不符合我们要求的,它比较的是地址,char*应该用strcmp。

??如果按照我们最简单的思路的话就是直接将T换成char*,但这样编译却给出了error,说这个特化找不到对应的模板函数。

#include <cstring>
//模板函数声明
template <typename T>
bool greater(const T &a,const T &b);
//特化的模板函数的声明
template<>
bool greater<char*>(const char * &a,const char * &b);
int main()
{
    return 0;
}
//模板函数定义
template <typename T>
bool greater(const T &a,const T &b)
{
    if(a > b)
        return true;
    else
        return false;
}
//特化的模板函数的定义
template<>
bool greater<char *>(const char * &a,const char * &b)
{
    return strcmp(a,b)>0?true:false;
}

??我们模板函数的定义const T &a,其实也可以是这种写法T const &a,这两种写法表明const和T分别修饰a,也就是a的类型既是const又是T;而不是const T作为一个整体,a的类型是const T。虽然在这个问题上,这两种理解没有出现语义的误解,但是在上面的例子就出现误解了。

? 根据我们原来的模板函数的定义,我们的目的应该是这样的特化函数的参数,const (char *) &a(是没有这种写法,只是为了让我们理解方便),也就是说char *是一个整体,和const一起修饰a。const char* &a却让const char作为了一个类型,这显然不是我们要的。char* const &a这才是我们想要的。

#include <cstring>
//模板函数声明
template <typename T>
bool greater(T const &a,T const &b);
//特化的模板函数的声明
template<>
bool greater<char*>(char * const &a,char * const &b);
int main()
{
    return 0;
}
//模板函数定义
template <typename T>
bool greater(T const &a,T const &b)
{
    if(a > b)
        return true;
    else
        return false;
}
//特化的模板函数的定义
template<>
bool greater<char*>(char * const &a,char * const &b)
{
    return strcmp(a,b)>0?true:false;
}

??如果在写类型时,习惯将const放在char等后面,那么写模板特化时,直接代换T就不会出现错误。

??如果在写类型时,习惯将const放在类型char等后面,那么写模板特化时,直接代换T就不会出现错误。

定义与实现分离?

??在传统上,我们总是把定义写在.h文件里,而实现文件写在.cpp文件里,但这在模板里面是否可以,请看下面一个例子。

//swap.h
template <typename T>
void swap(T &a,T &b);
//swap.cpp
template <typename T>
void swap(T &a,T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
//main.cpp
#include "swap.h"
int main()
{
    int a,b;
    swap(a,b);
    //...
    return 0;
}

??编译器在编译main.cpp文件时只看到swap的定义而没有实现,所以留空,让连接器去链接swap的实现。而编译器在编译swap.cpp时没有看到模板参数,所以也不会编译,最后便会导致链接错误,即找不到swap

??所以模板函数或者模板类,应该将定义和实现放在.h文件。

显示实例化(explict initialization)

??实例化:一个通过使用具体值替换模板参数,从模板产生的普通类,函数或者成员函数的过程。
??隐式实例化:这是编译器看到模板函数时,在当前文件实现相应的模板参数的实例化。
??显示实例化:就是自己手工让编译器在此文件实现相应的模板参数的实例化。
既然编译器会自动实现实例化,为什么还要我们去手工去让编译器实现实例化呢?请看下面的例子。

//swap.h
template <typename T>
void swap(T &a,T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
//function.h
void function();
//function.cpp
#include "swap.h"
void function()
{
    int a,b;
    swap(a,b);
}
//main.cpp
#include "swap.h"
#include "function.h"
int main()
{
    int a,b;
    swap(a,b);
    function();
    //...
    return 0;
}

??为了容易看出,我们暂且用function表示一个用到swap的函数,它也可以是一个类。
??编译器在编译function.cpp时会用void swap

//swap.h
template <typename T>
void swap(T &a,T &b);
//swap
templatee <typename T>
void swap(T &a,T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
//explict_initilization.cpp
#include "swap.cpp"
template void swap<int>(int&,int&);//显示实例化
//function.h
void function();
//function.cpp
#include "swap.h"
void function()
{
    int a,b;
    swap(a,b);
}
//main.cpp
#include "swap.h"
#include "function.h"
int main()
{
    int a,b;
    swap(a,b);
    function();
    //...
    return 0;
}

更加详细的介绍可以看c++模板类(一)理解编译器的编译模板过程

export的用法

??为了解决上面用一个explict_initilization.cpp来管理实例化文件的不便利,c++可以export这个关键词,让编译器和链接器去管理我们上面要解决的事情。

c++模板函数

标签:目的   链接   function   error   简单的   理解   body   找不到   声明   

原文地址:https://www.cnblogs.com/h-hg/p/8729098.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!