我们调用函数时,只要之前有函数声明就行,实现可以放到后面。所以我们通常将类定义(class definition)和全局函数声明(decleration)放到头文件,而将它们的定义(definition)放到源文件。
但是模板的情况有所不同,虽然如前文所述,模板是在我们具体用到时才实例化。
当我们调用模板函数或模板类的成员函数时,编译器此时需要该函数的定义(definition),也就是平时我们放在源文件的那些东西。
标准C++有两种模板编译模型,差别在于源文件中的“定义们”怎样提供给编译器,基本上所有的编译器都支持第一种模型,第二种相对少一些。
(1) Includsion Compilation Model 这种模型中,所有使用的模板的定义必须对编译器可见。比如一个头文件myhead.h如下
#ifndef MYHEAD_H_
#define MYHEAD_H_
//一些类定义,普通函数声明等等
template <typename T>
int func5(const T,const T){}
#include "mysource.cpp"
#endif
|
注意:倒数第二行有导入相应的源文件。我们使用的源文件如下:
template <typename T>
int func5(const T a,const T b){
if(a<b) return 0;
else return 1;
}
|
这就保证模板实例化时其定义对编译器可见。
但也带来了相应的问题,如果多个源文件使用同一个模板,编译器可能会产生多个实例,造成编译时开销较大,但在连接时会进行舍弃.
(2) Separate Complation Model 此模型中,编译器为我们追踪模板的定义,需要使用关键字 export,导出相应的模板,一个模板只能被导出一次。并且在模板声明处不能出现。
1.导入函数模板
export template <typename T>
int func5(const T a,const T b){
if(a<b) return 0;
else return 1;
}
|
在关键字template前加关键字export,而在相应头文件里,模板的声明处不能有export。
2.导入类模板,相对复杂一些
export template<class T> class Myclass;
#include "Myclass.h"
//其它
|
我们在源文件中使用了export关键字,但如果是在头文件中使用了export,那么该头文件只能被一个源文件所导入。
导出类的全部成员将变为导出的。也可以只对某成员进行导出,将export加在相应的前面。而剩下的未导出的类成员需要按第一种模型对待。
阅读(1044) | 评论(0) | 转发(0) |