c++模板编译模型

编译器只有在用到模板时,如调用了函数模板或调用了类模板的对象的时候,编译器才产生特定类型的模板实例。

编译时,模板与普通函数、类的区别:

  • 普通函数,只需函数声明,声明与定义分离;
  • 类类型,类定义可用,但成员函数只需声明,成员函数声明与定义分离;
  • 模板,要进行实例化,必须包含函数模板或类模板成员函数的定义。

标准 C++ 编译模板代码的两种模型:包含编译、分别编译

相同点:构造程序的方式相同----类定义和函数声明放在头文件中,而函数定义和成员定义放在源文件中。

不同点:编译器怎样使用来自源文件的定义,包含编译必须看到所有模版定义,而分别编译会自动跟踪所有模版定义。

所有编译器都支持包含编译模型,只有一些编译器支持分别编译模型。


一、包含编译模型

在包含编译模型中,编译器必须看到用到的所有模板的定义。一般而言,可以通过在声明函数模板或类模板的头文件中添加一条 #include指示使定义可用,该#include 引入了包含相关定义的源文件:

[cpp]  view plain  copy
  1. // 头文件 Compare.h  
  2. #ifndef COMPARE_H   
  3. #define COMPARE  
  4.   
  5. template <class T> int compare( const T&, const T& );  
  6. // 其他声明  
  7.   
  8. #include "Compare.cpp"  //获得compare 的定义   
  9. #endif  

[cpp]  view plain  copy
  1. //  源文件 Compare.cpp   
  2. #include "Compare.h"  
  3. template <class T> int compare( const T &v1, const T &v2 )  
  4. {  
  5.     if (v1 < v2) return -1;  
  6.     if (v2 < v1) return 1;  
  7.     return 0;  
  8. }  
  9. // 其他定义  

包含编译使得头文件和实现文件的分享,但是需要保证编译器在编译使用模板的代码时能看到两种文件。

某些使用包含模型的编译器,可以产生多个实例。如果两个或多个单独编译的源文件使用同一模板,这些编译器将为每个文件中的模板产生一个实例。通常,这种方法意味着给定模板将实例化超过一次。在预链接阶段,编译器会选择一个实例化而丢弃其他的。

包含编译在包含定义文件时,注意:

  • 头文件 Compare.h 包含 #include "Compare.cpp" ;
  • 并不把Queue.cpp添加到工程中,也就是Queue.cpp并不直接参与编译链接。

二、分别编译模型

通常用 export 关键字使编译器能够跟踪相关的模板定义。export 关键字能够指明给定的定义可能会需要在其他文件中产生实例化。在一个程序中,个模板只能定义为导出一次。编译器在需要产生这些实例化时计算出怎样定位模板定义。export 关键字不必在模板声明中出现。

函数模板:一般在函数模板的定义中指明export,这是通过在关键字template 之前包含 export 关键字而实现的:

[cpp]  view plain  copy
  1. // 头文件 Compare.h  
  2. #ifndef COMPARE_H   
  3. #define COMPARE  
  4.   
  5. template <class T> int compare( const T&, const T& );  
  6. // 其他声明  
  7.   
  8. #endif  

[cpp]  view plain  copy
  1. //  源文件 Compare.cpp   
  2. #include "Compare.h"  
  3.   
  4. export template <class T> int compare( const T &v1, const T &v2 ) //export指明函数为导出类型  
  5. {  
  6.     if (v1 < v2) return -1;  
  7.     if (v2 < v1) return 1;  
  8.     return 0;  
  9. }  
  10. // 其他定义  

类模板:头文件中的类定义体不应该使用关键字 export,如果在头文件中使用了 export,则该头文件只能被程序中的一个源文件使用。应该在类的实现文件中使用 export

[cpp]  view plain  copy
  1. // 头文件 Queue.h  
  2. #ifndef QUEUE_H   
  3. #define QUEUE_H  
  4.   
  5. template <class T> class Queue{  
  6. public:  
  7.     void func();  
  8.     //其它类成员声明  
  9. };  
  10. // 其他声明  
  11.   
  12. #endif  

[cpp]  view plain  copy
  1. //  源文件 Queue.cpp   
  2. #include "Queue.h"  
  3.   
  4. export template <class T> class Queue; //指明类Queue为export导出类型  
  5. template <class T> Queue<T>::func()  
  6. {  
  7. //实现  
  8. }  
  9. // 其他定义  

转自:http://blog.csdn.net/xgf415/article/details/52959434

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值