3

One Definition Rule指出程序应该包含每个非内联函数的一个定义。对于模板类的成员,这并不完全清楚对我说:类方法的显式特殊化 - 已定义的符号

/////////// 
// Tfoo.h 
template<typename T> class A { 
    void foo(){} 
}; 

/////////// 
// intfoo.h 
#include <Tfoo.h> 
template<> class Foo<int> { 
    void foo(); // declaration only 
}; 
/*inline*/ void Foo<int>::foo(){} // definition 

/////////// 
// X.cpp 
#include <intfoo.h> 

/////////// 
// Y.cpp 
#include <intfoo.h> 

在这种情况下,无论是clientX.obj和clientY.obj有Foo<int>::foo的定义。链接器抱怨说,这个符号定义不止一次:

Y.obj : error LNK2005: "private: void __thiscall Foo<int>::foo(void)" 
([email protected][email protected]@@AAEXXZ) already defined in X.obj 

当我在前面加上inlineFoo<int>::foo()定义,一切顺利和链接是幸福的。另外当我在一个单独的编译单元中定义它们的方法(例如intfoo.cpp)。

(注:这个解决方案是在https://stackoverflow.com/a/1481796/6610建议)

可能是一个误解,但不是模板类总是“内联”的成员函数?这里的规则是什么?

+1

什么[这里](http://stackoverflow.com/questions/3694899/c-template-and-inline)? – 2013-04-23 08:31:33

回答

7

类模板的显式特化的成员函数就像普通类的成员函数一样。毕竟,明确的专业一个不依赖于任何模板参数的具体类。

如果将其定义放入由多个翻译单元包含的头文件中,编译器将在处理每个翻译单元时为该函数生成目标代码。

最终,链接器会抱怨多重定义的符号。 inline关键字可防止此行为,就像它对常规非模板函数或非模板类的常规成员函数一样。

+0

“明确的专业化是一个具体的课程”:这就是我一直在寻找的。谢谢。 – xtofl 2013-04-23 08:35:16

+0

@xtofl:很高兴帮助 – 2013-04-23 08:38:26

0

您可以将明确的专业化

void Foo<int>::foo() {}

的定义放在.cpp文件。 留在.H声明:

template<> 
void Foo<int>::foo(); 
+0

...冒着你忘记构建+链接实现的风险。 – xtofl 2013-10-13 09:44:23