我有以下代码在VC6中编译:
Text.h:
template <typename T>
class CTextT
{
public:
friend CTextT add(const CTextT& text1, const CTextT& text2) ;
friend CTextT operator+(const CTextT& string1, const CTextT& string2)
{
return ::add(string1, string2);}
}
....................
};
在标题的末尾
#include "Text.inl"
Text.inl:
template <typename T>
CTextT<T> add(const CTextT<T>& text1, const CTextT<T>& text2)
{
CTextT<T> temp ;
// do something
return temp ;
}
但是VC2010给了我LINK错误:
error LNK2019: unresolved external symbol "class CTextT<char> __cdecl add(class CTextT<char> const &,class CTextT<char> const &)" (?add@@YA?AV?$CTextT@D@@ABV1@0@Z)
referenced in function "class CTextT<char> __cdecl operator+(class CTextT<char> const &,class CTextT<char> const &)" (??H@YA?AV?$CTextT@D@@ABV0@0@Z)
1>.\Debug\UnitTestText.exe : fatal error LNK1120: 1 unresolved externals
如果我将代码放在Text.h中,它编译得很好。但我不想这样做,因为我想保持声明清洁实施。在函数超出类的时候,我无法理解为什么链接器会在这种情况下抱怨?这是唯一的问题,类非常大,还有其他朋友函数返回CTextT。
答案 0 :(得分:2)
当然它确实会出现链接器错误。您创建的add()
函数friend
不是函数模板!它是在类模板中声明的非模板函数。因此,您也无法将此功能定义为模板。您可以在friend
声明中直接定义它。
另一种方法是在类模板之前声明函数模板。当然,这也需要声明类模板。以下应该有效:
template <typename T> class CTextT;
template <typename T> CTextT<T> add(CTextT<T> const&, CTextT<T> const&);
template <typename T>
class CTextT
{
friend CTextT<T> add<>(CTextT<T> const&, CTextT<T> const&);
// ...
};
现在您提供的模板定义应该有效。
答案 1 :(得分:0)
解决方案如下:
template <typename T>
class CTextT
{
public:
template <typename T>
friend CTextT<T> add(CTextT<T> const&, CTextT<T> const&) ;
friend CTextT<T> operator+(const CTextT<T>& string1, const CTextT<T>& string2)
{ return ::add(string1, string2); }
};
template <typename T>
CTextT<T> add(CTextT<T> const&, CTextT<T> const&)
{
CTextT<T> temp ;
return temp ;
}
我找到了MSDN的以下链接,解释了如何在模板中添加好友功能 - http://msdn.microsoft.com/en-us/library/f1b2td24.aspx。
我测试了它适用于VS2010和VS2012。 VC6不需要第二个模板声明(它从类中获取),而在VC6中,此代码将不再编译 - 将返回INTERNAL COMPILER ERROR。