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