C 模板類宣告和實現遇到的問題

2021-09-29 17:21:54 字數 1987 閱讀 8758

宣告乙個 模板類的標頭檔案 stack.h

#include #include templateclass stack ;
另外宣告乙個模板類的實現檔案 stack.cpp

#include "stack.h"

templatevoid stack::push(t const &elem)

templatevoid stack::pop()

templatet const &stack::top() const

templatebool stack::empty() const

在 main 裡使用這個模板類

#include #include "stack.h"

int main()

main.cpp:6: undefined reference to `stack::empty() const'

main.cpp:7: undefined reference to `stack::push(int const&)'

main.cpp:8: undefined reference to `stack::top() const'

main.cpp:9: undefined reference to `stack::pop()'

main.cpp:10: undefined reference to `stack::empty() const'

main.cpp:11: undefined reference to `stack::pop()'

分析模板例項化的過程:

編譯器使用模板,通過更換模板引數來建立資料型別。這個過程就是模板例項化(instantiation)。

從模板類建立得到的型別稱之為特例(specialization)。 

模板例項化取決於編譯器能夠找到可用**來建立特例(稱之為例項化要素,point of instantiation)。

要建立特例,編譯器不但要看到模板的宣告,還要看到模板的定義。

模板例項化過程是遲鈍的,即只能用函式的定義來實現例項化。

再回頭看上面的例子,可以知道stack是乙個模板,stack是乙個模板例項 - 乙個型別。從stack建立stack的過程就是例項化過程。例項化要素體現在main.cpp檔案中。如果按照傳統方式,編譯器在stack.**件中看到了模板的宣告,但沒有 模板的定義,這樣編譯器就不能建立型別stack。但這時並不出錯,因為編譯器認為模板定義在其它檔案中,就把問題留給鏈結程式處理。

現在,編譯stack.cpp時會發生什麼問題呢?編譯器可以解析模板定義並檢查語法,但不能生成成員函式的**。它無法生成**,因為要生成**,需要知道模板引數,即需要乙個型別,而不是模板本身。

這樣,鏈結程式在main.cpp 或 array.cpp中都找不到stack的定義,於是報出無定義成員的錯誤。

解決方法:

第一種方法意味著在使用模板的轉換檔案中不但要包含模板宣告檔案,還要包含模板定義檔案。這樣編譯器就能看到模板的宣告和定義,並由此生成 stack例項。這樣做的缺點是編譯檔案會變得很大,顯然要降低編譯和鏈結速度。

第二種方法,通過顯式的模板例項化得到型別。最好將所有的顯式例項化過程安放在另外的檔案中。在本例中,可以建立乙個新檔案templateinstantiations.cpp:      

#include "stack.cpp"

template class stack; // 顯式例項化

stack型別不是在main.cpp中產生,而是在templateinstantiations.cpp中產生。這樣鏈結器就能夠找到它的定義。用 這種方法,不會產生巨大的標頭檔案,加快編譯速度。而且標頭檔案本身也顯得更加「乾淨」和更具有可讀性。但這個方法不能得到惰性例項化的好處,即它將顯式地生 成所有的成員函式。另外還要維護templateinstantiations.cpp檔案。

第三種方法是在模板定義中使用export關鍵字,剩下的事就讓編譯器去自行處理了。

reference:

1.2.

C 中模板類的宣告和實現分離問題

有兩種方法 第1種 使用 tpp 檔案實現類模板的介面與實現的檔案分離 在.h檔案中放介面,在.tpp檔案中放實現,但這種方法得在.h檔案中,類的定義下面通過 include包含 tpp 檔案,如下 檔案 放類模板的介面 pragma once templateclass templateclass...

C 類模板的宣告和實現不能分離

也許你具有良好的程式設計習慣,在定義乙個類的時候總會把宣告和實現分離開,位於不同的檔案中。比如你定義乙個類a,首先建立乙個.h檔案,如下 class a 接下來你建立乙個.cpp檔案實現類的宣告,如下 include classa.h include a a int b void a show a ...

C 模板類的宣告

c 的模板類感覺跟c 的泛型非常相似,自己寫了個例子試試,結果一大堆錯誤,後來慢慢除錯,發現模板類的宣告和定義不能分開 必須在同乙個檔案中 否則在使用模板類的會報乙個錯誤 無法解析的外部符號.該符號在函式 main 中被引用 然後把函式的定義全部挪到類的宣告裡面去後,就可以了通過了。看了好多人的例子...