例如,我有Test.h一个类模板,其中定义了类模板,并且以隐式Test方式Test.cpp定义了类的方法和构造函数,但在main.cpp我初始化的某个地方Test<int> testValue。由于编译器不知道如何Type在Test.cpp. 一个人如何“作弊”(不使用额外的第三类文件.inl或其他任何东西)
测试.h
#ifndef Test
#define Test
template <class Type>
class Test
{
private:
Type value;
public:
Test(Type valueOfUser);
Type getValue();
};
#endif // Test
测试.cpp
#include "Test.h"
template <typename Type> Test<Type>::Test(Type valueOfUser): value(valueOfUser) {}
template <typename Type> Type Test<Type>::getValue () { return value; }
主文件
#include "Test.h"
intt main()
{
Test<int> test;
test.getValue();
return 0;
}
他们告诉世界多少次......(c)
不要将模板函数/类定义放在单独的 .cpp 文件中。仅将所有内容放在头文件中 - 否则不会发生实例化,因此我们拥有我们所拥有的。
来自 Stroustrup 的建议(A Tour of C++,adv. 7-6):
自己想想 - 在编译 Test.cpp 文件时,编译器如何知道(使用什么模板参数)将在另一个文件中实例化?
在另一个文件(main.cpp)中——如果无法访问实现代码,你怎么知道如何实例化模板?
解决方法是在模板实现文件中显式实例化所需的类型
是可能的,但是很不方便——下次你
main.cpp需要一个新类型的类,你需要立即将它添加到test.cpp. 更糟糕的是,如果某些类型变得不必要,但继续被实例化和链接。有一种方法,但不方便。
B
test.cpp可以通过添加到文件末尾来显式实例化class Test:Type = int不便之处在于,
.cpp您必须在文件中列出您计划使用该类的所有模板参数集。这是最后的手段。更好地听@Harry 并将模板函数定义保留在头文件中。
首先,您的方法的失败与“编译器不知道如何在 Test.cpp 中定义我的类型”无关。你不断地从一个问题到另一个问题重复这一点,但这与问题的本质无关。
其次,您有机会强制某些东西在此版本中工作:通过在
.cpp文件中显式实例化您的定义,以用于在程序中使用您的模板的那些类型。但这通常是对显式实例化能力的不当使用。模板的全部意义在于编译器本身应该自动确定程序中需要哪些版本的模板实体并自动生成它们。这要求所有模板定义在任何地方都是可见的,而不是隐藏在某个
.cpp文件中。语言中存在显式实例化的可能性主要是为了优化这个过程,而不是用手动实例化代替自动实例化。