7 回答

TA貢獻(xiàn)1795條經(jīng)驗(yàn) 獲得超7個(gè)贊
它是不是需要把執(zhí)行的頭文件,看到這個(gè)答案的末尾替代解決方案。
無(wú)論如何,代碼失敗的原因是,在實(shí)例化模板時(shí),編譯器會(huì)創(chuàng)建一個(gè)具有給定模板參數(shù)的新類。例如:
template<typename T>struct Foo{ T bar; void doSomething(T param) {/* do stuff using T */}};// somewhere in a .cppFoo<int> f;
讀取此行時(shí),編譯器將創(chuàng)建一個(gè)新類(讓我們調(diào)用它FooInt
),這相當(dāng)于以下內(nèi)容:
struct FooInt{ int bar; void doSomething(int param) {/* do stuff using int */}}
因此,編譯器需要訪問(wèn)方法的實(shí)現(xiàn),以使用模板參數(shù)(在本例中int
)實(shí)例化它們。如果這些實(shí)現(xiàn)不在標(biāo)頭中,則它們將不可訪問(wèn),因此編譯器將無(wú)法實(shí)例化模板。
一個(gè)常見(jiàn)的解決方案是在頭文件中編寫模板聲明,然后在實(shí)現(xiàn)文件(例如.tpp)中實(shí)現(xiàn)該類,并在頭的末尾包含此實(shí)現(xiàn)文件。
// Foo.htemplate <typename T>struct Foo{ void doSomething(T param);};#include "Foo.tpp"// Foo.tpptemplate <typename T>void Foo<T>::doSomething(T param){ //implementation}
這樣,實(shí)現(xiàn)仍然與聲明分離,但編譯器可以訪問(wèn)。
另一種解決方案是保持實(shí)現(xiàn)分離,并顯式實(shí)例化您需要的所有模板實(shí)例:
// Foo.h// no implementationtemplate <typename T> struct Foo { ... };//---------------------------------------- // Foo.cpp// implementation of Foo's methods// explicit instantiationstemplate class Foo<int>;template class Foo<float>; // You will only be able to use Foo with int or float
如果我的解釋不夠清楚,你可以看一下關(guān)于這個(gè)主題的C ++ Super-FAQ。

TA貢獻(xiàn)1998條經(jīng)驗(yàn) 獲得超6個(gè)贊
這里有很多正確答案,但我想補(bǔ)充一下(為了完整性):
如果您在實(shí)現(xiàn)cpp文件的底部對(duì)模板將使用的所有類型進(jìn)行顯式實(shí)例化,則鏈接器將能夠像往常一樣找到它們。
編輯:添加顯式模板實(shí)例化的示例。在定義模板后使用,并且已定義所有成員函數(shù)。
template class vector<int>;
這將實(shí)例化(并因此使鏈接器可用)類及其所有成員函數(shù)(僅)。類似的語(yǔ)法適用于模板函數(shù),因此如果您有非成員運(yùn)算符重載,則可能需要對(duì)它們執(zhí)行相同的操作。
上面的例子是相當(dāng)無(wú)用的,因?yàn)関ector是在頭文件中完全定義的,除非公共包含文件(預(yù)編譯頭文件?)使用extern template class vector<int>
它以防止它在使用vector的所有其他(1000?)文件中實(shí)例化它。

TA貢獻(xiàn)1886條經(jīng)驗(yàn) 獲得超2個(gè)贊
在將模板實(shí)際編譯為目標(biāo)代碼之前,模板需要由編譯器實(shí)例化。只有在模板參數(shù)已知的情況下才能實(shí)現(xiàn)此實(shí)例化?,F(xiàn)在想象一下模板函數(shù)在其中聲明a.h
,定義a.cpp
和使用的場(chǎng)景b.cpp
。在a.cpp
編譯時(shí),不一定知道即將進(jìn)行的編譯b.cpp
將需要模板的實(shí)例,更不用說(shuō)具體的實(shí)例。對(duì)于更多的頭文件和源文件,情況可能會(huì)變得更加復(fù)雜。
有人可以說(shuō),編譯器可以變得更聰明,可以“預(yù)見(jiàn)”模板的所有用途,但我確信創(chuàng)建遞歸或其他復(fù)雜場(chǎng)景并不困難。AFAIK,編譯器不會(huì)這樣做。正如Anton所指出的,一些編譯器支持模板實(shí)例化的顯式導(dǎo)出聲明,但并非所有編譯器都支持它(但是?)。

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊
雖然標(biāo)準(zhǔn)C ++沒(méi)有這樣的要求,但是一些編譯器要求所有函數(shù)和類模板都需要在它們使用的每個(gè)轉(zhuǎn)換單元中可用。實(shí)際上,對(duì)于那些編譯器,模板函數(shù)的主體必須在頭文件中可用。重復(fù):這意味著那些編譯器不允許在非頭文件中定義它們,例如.cpp文件
有一個(gè)導(dǎo)出關(guān)鍵字可以緩解這個(gè)問(wèn)題,但它遠(yuǎn)不是可移植的。
- 7 回答
- 0 關(guān)注
- 1605 瀏覽
添加回答
舉報(bào)