我有一个名为“SimObject”的类:
namespace simBase
{
class __declspec(dllexport) SimObject: public SimSomething
{
public:
template <class T>
void updateParamValue( const std::string& name, T val );
}
}
我有另一个名为“ITerrainDrawable”的类:
namespace simTerrain
{
class __declspec(dllexport) ITerrainDrawable : public simBase::SimObject
{
}
}
这些类位于不同的库中。 SimObject在simBase中,ITerrainDrawable在simTerrain库中。即使ITerrainDrawable派生自SimObject并且我包含了simBase库,我也会收到链接错误:
未解析的外部符号
1>ITerrainDrawable.obj : error LNK2019: unresolved external symbol "public: void __thiscall simBase::SimObject::updateParamValue<float>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,float)" (??$updateParamValue@M@SimObject@simBase@@QAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@M@Z) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setTerrainSize(float)" (?setTerrainSize@ITerrainDrawable@simTerrain@@QAEXM@Z)
1>ITerrainDrawable.obj : error LNK2019: unresolved external symbol "public: void __thiscall simBase::SimObject::updateParamValue<class osg::Vec4f>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class osg::Vec4f)" (??$updateParamValue@VVec4f@osg@@@SimObject@simBase@@QAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VVec4f@osg@@@Z) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setSatelliteTextureBorders(class osg::Vec2f,class osg::Vec2f)" (?setSatelliteTextureBorders@ITerrainDrawable@simTerrain@@QAEXVVec2f@osg@@0@Z)
为什么我会收到此错误?
如果我不使用模板功能但是我需要它,一切正常。
如果我将此函数移动到simTerrain库它可以正常工作,但我不想使用重复函数,因为有很多库像simTerrain。
答案 0 :(得分:11)
C ++并不真正支持单独编译模板代码 - 您需要将模板的定义放在头文件中。
答案 1 :(得分:6)
模板有两种编译模型:
您可以在第二个选项的模板定义时使用导出关键字。
export template <class T>
void updateParamValue( const std::string& name, T val ) {}
但我不确定所有编译器都支持它。
答案 2 :(得分:5)
模板类的完整实现必须位于该模板类的标头中。 C ++的ANSI / ISO标准允许使用 export 关键字将实现放在单独的编译单元中,但目前有任何编译器实际支持这一点。
答案 3 :(得分:4)
以下是工作示例:
template<class T> TEST_API void foo(T)
{
std::cout << "test";
}
template TEST_API void foo(int);
template TEST_API void foo(char);
转储文件test.dll
文件类型:DLL
部分包含test.dll的以下导出
00000000 characteristics
4FDEF629 time date stamp Mon Jun 18 12:34:33 2012
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint RVA name
1 0 00001032 ??$foo@D@@YAXD@Z = @ILT+45(??$foo@D@@YAXD@Z)
2 1 00001014 ??$foo@H@@YAXH@Z = @ILT+15(??$foo@H@@YAXH@Z)
答案 4 :(得分:3)
您需要指定(cpp文件很好)模板专业化。这意味着您需要导出所有模板参数组合,您将使用:
template __declspec(dllexport) void updateParamValue<int>( const std::string& name, T val );
template __declspec(dllexport) void updateParamValue<short>( const std::string& name, T val );
......
我在Visual Studio 2013中使用它并且它可以工作。