我仍然无法让它发挥作用..
由于前向声明,我不得不将实现与我的一个泛型类的定义分开,我现在在尝试构建时遇到链接器错误。
IShader.h:
template <typename ShadeType>
class IShader {
public:
template <typename T>
bool getProperty(const std::string& propertyName, ShaderProperty<T>** outProp);
};
所以它是一个泛型类,具有通用成员函数,具有不同的泛型类型
实现如下:
#include "MRIShader.h"
template <typename ShadeType> template <typename T>
bool IShader<ShadeType>::getProperty(const std::string& propertyName, ShaderProperty<T>** outProp){
std::map<std::string, IShaderProperty* >::iterator i = m_shaderProperties.find(propertyName);
*outProp = NULL;
if( i != m_shaderProperties.end() ) {
*outProp = dynamic_cast<ShaderProperty<T>*>( i->second );
return true;
}
return false;
}
但是我得到像这样的链接器错误:
error LNK2001: Nicht aufgelöstes externes Symbol ""public: bool __thiscall IShader<class A_Type>::getProperty<bool>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class ShaderProperty<bool> * *)" (??$getProperty@_N@?$IShader@VA_Type@@@@QAE_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAPAV?$ShaderProperty@_N@@@Z)". SceneParser.obj
对于bool,但也适用于许多其他类型。 我已经阅读了这篇文章: http://www.parashift.com/c++-faq-lite/templates.html
但添加
templace class IShader<bool>;
在IShader.cpp的最后没有解决问题。 我还尝试在实现中的关键字“template”之前添加'export'关键字,但这只是给我一个语法错误。
声明和实现我的模板类的正确方法是什么,模板类在单独的文件(.h和.cpp)中具有模板化成员方法(具有不同的模板类型!)而不会出现链接器错误?
谢谢!
答案 0 :(得分:2)
您只在翻译单元中为类提供可链接对象,但成员函数是在另一个参数上模板化的,并且还必须明确指定。
我不知道是否有更优雅的方式,但一个可编辑的版本将是:
template bool IShader<bool>::getProperty<bool>
(const std::string& propertyName,
ShaderProperty<bool>** outProp);
VC8和GCC 3.4都允许在函数名后省略<bool>
。但是我不确定那种情况下的正确语法。
但只要您在大型项目中没有编译时间问题,请省去麻烦并将方法定义(标记为内联)放在标题中。
如果您只是担心头文件的大小,请将定义移到另一个头文件中,例如 IShaderImpl.h ,包含在 IShader.h 的末尾。
快速取样以消除疑虑:
// IShader.h
template<typename T>
struct ShaderProperty {};
template <typename T>
class IShader {
public:
template <typename U>
void getProperty(ShaderProperty<U>**);
};
// IShader.cpp
#include <iostream>
#include "IShader.h"
template<typename T> template<typename U>
void IShader<T>::getProperty(ShaderProperty<U>**)
{ std::cout << "moo" << std::endl; }
template class IShader<bool>;
template void IShader<bool>::getProperty(ShaderProperty<bool>**);
// main.cpp
#include "IShader.h"
int main() {
IShader<bool> b;
ShaderProperty<bool>** p;
b.getProperty(p);
}
答案 1 :(得分:0)
您是否在头文件中包含了cpp文件?
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13
请注意foo-impl.cpp #includes a .cpp文件,而不是.h文件。如果那样的话 令人困惑,点击你的高跟鞋两次, 想到堪萨斯,并在我之后重复, “尽管如此,我仍会这样做 令人困惑的。“你可以相信我 一。但如果你不相信我或是 简直好奇,
编辑我得到了这个编译:
//////////////////////////////////////////////////////////////////////////
// Foo.cpp - implementation of Foo
#include "stdafx.h"
template <typename ShadeType>
template <typename T>
bool IShader<ShadeType>::getProperty(ShaderProperty<T>** outProp){
*outProp = dynamic_cast<ShaderProperty<T>*>( NULL );
return false;
}
//////////////////////////////////////////////////////////////////////////
// Foo.h
template<typename T> class ShaderProperty
{
};
template <typename ShadeType>
class IShader {
public:
template <typename T>
bool getProperty(ShaderProperty<T>** outProp);
};
#include "Foo.cpp"
///Main.cpp
IShader<someclass> blah;
ShaderProperty<someclass2>* prop;
blah.getProperty(&prop);
所以换句话说,你无法真正隐藏库用户的实现代码。您可以在头文件中包含代码,也可以在头文件中包含cpp文件。
答案 2 :(得分:0)
C ++中的模板化类必须在同一文件中提供声明和实现。否则当另一个文件包含头时,链接器将无法找到那些可能的定义。