原文出处:
https://www.codeproject.com/Articles/48575/How-to-Define-a-Template-Class-in-a-h-File-and-Impwww.codeproject.comc++中常见的过程是将类定义放在一个c++头文件中,将实现放在一个c++源文件中。然后,源文件成为项目的一部分,这意味着它是单独编译的。但是当我们为模板类实现这个过程时,会出现一些编译和链接问题。
本文通过示例介绍了三种可能的解决方案:
1、您可以在实现模板类的同一个源文件中创建模板类的对象;
2、可以在main.cpp中包含实现模板类的源文件;
3、您可以在定义模板类(TestTemp.h)的头文件中包含实现模板类(TestTemp.cpp)的源文件,并从项目(而不是文件夹)中删除 实现模板类的源文件。
背景
c++中常见的过程是将类定义放在一个c++头文件中,将实现放在一个c++源文件中。然后,源文件成为项目的一部分,这意味着它是单独编译的。但是当我们为模板类实现这个过程时,会出现一些 编译和 链接问题。
编译问题
下面是一些示例代码:
// TestTemp.h
如果你尝试像上面所示的一般实现模板类,它会产生一组编译错误,如:
: error C2955: 'TestTemp' : use of class template requires template argument list
: error C2065: 'T' : undeclared identifier
在这种情况下,编译器不知道对象类型。所以它不能编译。
所以,我们在实现模板类的成员函数时,应添加<T>:
// TestTemp.h
链接问题
使用上述代码,在解决了所有编译错误之后,当您在TestTemp.cpp之外的任何文件中创建该类的对象时,可能会得到一些链接错误。下面是一些示例代码:
// main.cpp
链接错误:
: error LNK2001: unresolved external symbol "public: __thiscall
TestTemp<int>::TestTemp<int>(void)"
(??0?$TestTemp@H@@QAE@XZ)
原因
当编译器遇到某个特定类型的TestTemp对象声明时,例如int,它必须能够访问模板实现源。否则,它将不知道如何构造TestTemp成员函数。而且,如果将实现放在源文件(TestTemp.cpp)中,并将其作为项目的单独部分,则编译器在尝试编译mian.cpp源文件时将无法找到它(即,此时仅仅#include"TestTemp.h" 是不够的,这只告诉编译器如何分配对象数据和如何构建对成员函数的调用,而不是如何构建成员函数。同时,编译器不会抱怨,它将假定这些函数在其他地方提供,并让链接器来查找它们)。
因此,当需要链接时,您将获得对任何未在类定义中 定义为内联的类成员函数 的"unresolved references"。
解决
方法1
您可以在实现模板类的源文件中创建模板类的对象(TestTemp.cpp)。因此,不需要将对象创建代码与其在其他文件中的实际实现链接起来。这将导致编译器编译这些特定类型,以便关联的类成员函数在链接时可用。下面是示例代码:
模板类头文件
// TestTemp.h
模板类源文件
// TestTemp.cpp
“ TestTemp.cpp”中的临时函数将解决链接错误。不需要调用这个函数,因为它是全局的。
main.cpp源文件
// main.cpp
#include "TestTemp.h"
...
TestTemp<int> TempObj;
TempObj.SetValue( 2 );
int nValue = TempObj.Getalue();
...
方法2
可以在mian.cpp源文件中包含实现模板类的源文件。下面是示例代码:
模板类头文件
// TestTemp.h
模板类源文件
// TestTemp.cpp
main.cpp源文件
// main.cpp
方法3
您可以在定义模板类(TestTemp.h)的头文件中 #include实现模板类(TestTemp.cpp)的源文件,并从项目(而不是文件夹)中删除源文件。下面是示例代码:
模板类头文件
// TestTemp.h
模板类源文件
// TestTemp.cpp
main.cpp源文件
// main.cpp
注意:
不要忘记从项目中删除 实现模板类的那个源文件(在本文中,就是要remove掉:“TestTemp.cpp”)
![95c4f120bb2058dc13c21011c3d8ef5b.png](https://i-blog.csdnimg.cn/blog_migrate/fc6dda3131ab5294e4df2d72638364cf.png)