C++中模板类和模板成员函数不能分开写

       一个类一般都是在头文件(.h)中声明,在源文件(.cpp)中实现,但是在使用模板的时候,如果将模板成员函数分别放在头文件和源文件中则编译时会出现错误。错误原因是找不到链接。因为当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明。因此,最好的办法就是将模板的声明和定义都放置在同一个头文件(.h)中。这就是为什么所有的STL头文件都包含模板定义的原因。当然如果一定要在源文件(.cpp)中定义则在编译器支持的情况下可使用“export”关键字,即在模板成员函数的定义前面加上“export”,很遗憾的是visual studio和GCC是不支持此关键字,因此最好还是将声明和定义都写到头文件(.h)中。

       分离编译模式(Separate Compilation Model)允许在一处翻译单元(Translation Unit)中定义(define)函数、类型、类对象等,在另一处翻译单元引用它们。编译器(Compiler)处理完所有翻译单元后,链接器(Linker)接下来处理所有指向 extern 符号的引用,从而生成单一可执行文件。然而该模式却驯不服模板(Template)。标准要求编译器在实例化模板时必须在上下文中可以查看到其定义实体;而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的——原因很简单,编译器怎么会预先知道 typename 实参是什么呢?因此模板的实例化与定义体必须放到同一翻译单元中。

例:

templateClass.h

class TemplateClass
{
public:
	TemplateClass() {}
	~TemplateClass() {}
	template<typename T>
	T sum(T t1,  T t2);

	template<typename S>
	void print(S s);

private:

};

template<typename T>
T TemplateClass::sum(T t1, T t2)
{
	T s = t1 + t2;
	cout << "sum(): " << s << endl;
	return s;
}

template<typename S>
void TemplateClass::print(S s)
{
	cout << "print(): "<< s << endl;
}

main.cpp

int main()
{
	TemplateClass tem;
	tem.sum(1.5, 2.6);          // 自动调用,编译器根据传入的值来推导类型
	tem.sum<int>(123, 268);		// 显示调用,告诉编译器调用的是int类型
	tem.print("aaa");
	tem.print(123);

	system("pause");
	return 0;
}

输出:

原创文章 99 获赞 68 访问量 4万+

猜你喜欢

转载自blog.csdn.net/King_weng/article/details/103829941