c++ 模板编程

类模板

类模板——模板类(class template——template class)
类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例子:

template <typename T>
class Vector
{
    ...
};

具体实例

#include <iostream>
#include <string>
using namespace std;
template<class T1,class T2=string>
class show
{
public:
    void show1(T1 &a){cout<<"show1:"<<a<<endl;}
    void show2(T2 &a){cout<<"show2:"<<a<<endl;}
};
 
int main()
{
    show<int> a;
    int temp1=5;
    string temp2="Hello,C++!";
    a.show1(temp1);
    a.show2(temp2);
    return 0;
}

函数模板

函数模板——模板函数(function template——template function)
函数模板的重点是模板。表示的是一个模板,专门用来生产函数。例子:

template<typename  T>  
void fun(T a)  
{  
  ...
}   

C++模板全特化、偏特化

全特化

特化其实就是特殊化的意思,在模板类里,所有的类型都是模板(template),而一旦我们将所有的模板类型T都明确化,并且写了一个类名与主模板类名相同的类,那么这个类就叫做全特化类。C++模板全特化之后已经失去了Template的属性了。
//模板函数
template<typename T, class N> void func(T num1, N num2)
{
//cout << “num1:” << num1 << “, num2:” << num2 <<endl;
}

//模板类
template<typename T, class N> class Test_Class
{
public:
    static bool comp(T num1, N num2)
    {
        return (num1<num2)?true:false;
    }
};
 
//全特化,模板函数
template<> void func(int num1, double num2)
{
    cout << "num1:" << num1 << ", num2:" << num2 <<endl;
}
 
//全特化,模板类
template<> class Test_Class<int, double>
{
public:
    static bool comp(int num1, double num2)
    {
        return (num1<num2)?true:false;
    }
};

调用

func<int, double>(1, 2.0);
Test_Class<int, double>::comp(1, 2.0);

注意:一个模板被称为全特化的条件:1.必须有一个主模板类 2.模板类型被全部明确化

C++模板偏特化

上面对主版本模板和全特化进行了定义,那么偏特化就是介于二者之间的模板,它的模板名与主版本模板名相同,但是它的模板型中,有被明确化的部分和没有被明确化的部分。

//模板函数
template<typename T, class N> void func(T num1, N num2)
{
    //cout << "num1:" << num1 << ", num2:" << num2 <<endl;
}
 
//模板类
template<typename T, class N> class Test_Class
{
public:
    static bool comp(T num1, N num2)
    {
        return (num1<num2)?true:false;
    }
};
 
//偏特化,模板函数
template<class N> void func(int num1, N num2)
{
    cout << "num1:" << num1 << ", num2:" << num2 <<endl;
}
 
//偏特化,模板类
template<class N> class Test_Class<int, N>
{
public:
    static bool comp(int num1, double num2)
    {
        return (num1<num2)?true:false;
    }
};

调用

func<int, double>(1, 2.0);
Test_Class<int, double>::comp(1, 2.0);

注意:偏特化的条件:1.必须有一个主模板 2.模板类型被部分明确化

C++模板类代码只能写在头文件?

最近写个模板类玩的时候,发现将模板的定义与时间分开写会报错。

当我非常仔细的将定义和实现分开,在头文件中保留了最少的依赖后,一切就绪.cpp单独编过。但是当使用的时候,就会报告所有的函数调用都没有实现。按常规.h/.cpp而言这是不可能的。但是模板类就是这么独特。简单说说他的原因,也备自己将来遗忘:

从语法角度而言,是没有强制要求说模板代码的声明和实现不可以分开。那么当分离的声明和实现写好后,单独编译.cpp是可以通过的,但是生成的.o文件却非常小,只有一个原因:确实没有任何实现代码!————不知道用什么类型参数套用模板。

因为模板类需要在使用到的地方利用声明模板的typename或者class参数的时候,才会即时生成代码。那么当我把模板声明和实现分开的时候,这个即时过程因为编译器只能通过代码include“看到”头文件而找不到模板实现代码,所以会产生链接问题。这也是为什么几乎都会建议模板类和声明和实现都写在头文件。

如果刚接触c/c++编写的朋友可能还不是很明白。编译器面对巨量代码的时候,也是以一个一个的.cpp/.c文件作为基本单元,根据代码的include包含找到声明,翻译代码产生.o文件。注意他们每个cpp/c文件都是相互独立完成自己工作的,对于缺少的部分,如果妥善声明,会留待链接过程的时候产生引用关系。 那么刚才说的模板类实现代码,编译它的时候因为不知道套用什么参数,实际上没有任何有用的内容存在于.o文件当中。而在使用模板类的地方指定了类型参数,编译器这才开始根据模板代码产生有用的.o编码,可是这些内容放在了使用模板的代码产生的.o文件当中。如果编使用模板代码的时候,通过include包含“看不到”模板的实现代码,这些所有的缺失,到链接阶段就无法完成。

引用C++primer的话:C++支持两种模板编译模式包含模式Inclusion Model 和分离模式Separation Model

1. 包含编译模式

在包含编译模式下我们在每个模板被实例化的文件中包含函数模板的定义并且往往把定义放在头文件中像对内联函数所做的那样

2. 分离编译模式

在分离编译模式下函数模板的声明被放在头文件中 , 在模板定义中有一个关键字export, 关键字export 告诉编译器在生成被其他文件使用的函数模板实例时可能需要这个模板定义编译器必须保证在生成这些实例时该模板定义是可见的 , 关键字export 不需要出现在头文件的模板声明中, 分离模式使我们能够很好地将函数模板的接口同其实现分开进而组织好程序以便把函数模板的接口放到头文件中而把实现放在文本文件中, 但是并不是所有的编译器都支持分离模式, 即使支持也未必总能支持得很好, 支持分离模式需要更复杂的程序设计环境所以它们不能在所有C++编译器实现中提供.

理解: 现在的VC++编译器都不知道模板分离编译模式,所以还是要把定义与实现都放在一个文件中。
C++类模板的声明和定义通常放在同一个文件

不是只能放在.h里面,但是推荐放在.h里面。STL模板实现全部是放在.h里面的。

模板需要注意的地方

  • typename 不能为 void?
  • 可以在模板调用模板函数
  • 可以使用单例模式对模板赋值

参考文献:
https://blog.csdn.net/jinzeyu_cn/article/details/45795923
https://blog.csdn.net/qq_18108083/article/details/84064990
https://blog.csdn.net/zhuzhaoming1994/article/details/80346250
https://blog.csdn.net/qq_38790716/article/details/89475618
https://blog.csdn.net/m_buddy/article/details/72973207

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值