亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么模板只能在頭文件中實現?

為什么模板只能在頭文件中實現?

墨色風雨 2019-05-20 15:26:20
引自C ++標準庫:教程和手冊:目前使用模板的唯一可移植方法是使用內聯函數在頭文件中實現它們。為什么是這樣?
查看完整描述

7 回答

?
一只萌萌小番薯

TA貢獻1795條經驗 獲得超7個贊

它是不是需要把執行的頭文件,看到這個答案的末尾替代解決方案。

無論如何,代碼失敗的原因是,在實例化模板時,編譯器會創建一個具有給定模板參數的新類。例如:

template<typename T>struct Foo{
    T bar;
    void doSomething(T param) {/* do stuff using T */}};// somewhere in a .cppFoo<int> f;

讀取此行時,編譯器將創建一個新類(讓我們調用它FooInt),這相當于以下內容:

struct FooInt{
    int bar;
    void doSomething(int param) {/* do stuff using int */}}

因此,編譯器需要訪問方法的實現,以使用模板參數(在本例中int)實例化它們。如果這些實現不在標頭中,則它們將不可訪問,因此編譯器將無法實例化模板。

一個常見的解決方案是在頭文件中編寫模板聲明,然后在實現文件(例如.tpp)中實現該類,并在頭的末尾包含此實現文件。

// Foo.htemplate <typename T>struct Foo{
    void doSomething(T param);};#include "Foo.tpp"// Foo.tpptemplate <typename T>void Foo<T>::doSomething(T param){
    //implementation}

這樣,實現仍然與聲明分離,但編譯器可以訪問。

另一種解決方案是保持實現分離,并顯式實例化您需要的所有模板實例:

// 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

如果我的解釋不夠清楚,你可以看一下關于這個主題C ++ Super-FAQ。


查看完整回答
反對 回復 2019-05-20
?
米琪卡哇伊

TA貢獻1998條經驗 獲得超6個贊

這里有很多正確答案,但我想補充一下(為了完整性):

如果您在實現cpp文件的底部對模板將使用的所有類型進行顯式實例化,則鏈接器將能夠像往常一樣找到它們。

編輯:添加顯式模板實例化的示例。在定義模板后使用,并且已定義所有成員函數。

template class vector<int>;

這將實例化(并因此使鏈接器可用)類及其所有成員函數(僅)。類似的語法適用于模板函數,因此如果您有非成員運算符重載,則可能需要對它們執行相同的操作。

上面的例子是相當無用的,因為vector是在頭文件中完全定義的,除非公共包含文件(預編譯頭文件?)使用extern template class vector<int>它以防止它在使用vector的所有其他(1000?)文件中實例化它。


查看完整回答
反對 回復 2019-05-20
?
MM們

TA貢獻1886條經驗 獲得超2個贊

在將模板實際編譯為目標代碼之前,模板需要由編譯器實例化。只有在模板參數已知的情況下才能實現此實例化。現在想象一下模板函數在其中聲明a.h,定義a.cpp和使用的場景b.cpp。在a.cpp編譯時,不一定知道即將進行的編譯b.cpp將需要模板的實例,更不用說具體的實例。對于更多的頭文件和源文件,情況可能會變得更加復雜。

有人可以說,編譯器可以變得更聰明,可以“預見”模板的所有用途,但我確信創建遞歸或其他復雜場景并不困難。AFAIK,編譯器不會這樣做。正如Anton所指出的,一些編譯器支持模板實例化的顯式導出聲明,但并非所有編譯器都支持它(但是?)。


查看完整回答
反對 回復 2019-05-20
?
倚天杖

TA貢獻1828條經驗 獲得超3個贊

雖然標準C ++沒有這樣的要求,但是一些編譯器要求所有函數和類模板都需要在它們使用的每個轉換單元中可用。實際上,對于那些編譯器,模板函數的主體必須在頭文件中可用。重復:這意味著那些編譯器不允許在非頭文件中定義它們,例如.cpp文件

有一個導出關鍵字可以緩解這個問題,但它遠不是可移植的。


查看完整回答
反對 回復 2019-05-20
  • 7 回答
  • 0 關注
  • 1632 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號