2010-10-07 94 views
0

在 「未定義的引用」 這些都是我的文件:模板函數被報道編譯

-------- [c.hpp] --------

#ifndef _C 
#define _C 

#include<iostream> 
class C 
{ 
public: 
    template<class CARTYPE> void call(CARTYPE& c); 
}; 

#endif 

-------- [c.cpp] --------

#include "c.hpp" 

template<class CARTYPE> void C::call(CARTYPE& c) 
{ 
    //make use of c somewhere here 
    std::cout<<"Car"<<std::endl; 
} 

-------- [v.cpp] --------

class Merc 
{}; 

-------- [main.cpp中] --------

#include "c.hpp" 
#include "v.cpp" 
//#include "c.cpp" 

int main() 
{ 
    Merc m; 
    C someCar; 
    someCar.call(m); 

}//main 

我能夠爲所有上述文件名爲 「.o」 文件,用命令g ++ -c main.cpp和g ++ -c c.cpp等等。 但是當我嘗試連接使用g ++ -o汽車合作main.o沃 的名爲「.o」文件,我得到這個錯誤:

main.o: In function `main': 
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)' 
collect2: ld returned 1 exit status 

錯誤消失,當我取消對該行的#include「c.cpp 「在main.cpp中,但我覺得用這種方式包含cpp文件可能是不好的做法。我做錯了嗎?在創建單獨的對象文件並鏈接它們時,是否有更好的方法來迎合模板聲明? p.s:我在更復雜的類結構中使用模板函數。這裏展示的僅僅是一個小例子,目的是向你展示我面臨的錯誤。

+3

請參閱http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – 2010-10-07 05:18:38

+0

@Pavel:您指出的解決方案是我需要的確切解決方案。謝謝:) – Nav 2010-10-07 06:15:14

回答

1

一種解決這個問題的方法是

a。從c.cpp刪除'#include'c.hpp''AND

b。在'c.hpp'(奇怪的聲音'#include「c.pp'')結尾處包括'c.cpp'

這樣模板定義可用於每個翻譯單元,包括'c.hpp'而不是在每個.cpp文件中明確這樣做。這就是所謂的'inclusion model'

+0

如果您對c.cpp中不應包含在每個翻譯單元中的東西的需求發展,它也會導致麻煩。 – 2010-10-07 05:55:35

+0

@Tony:哦,那你現在怎麼辦? – Chubsdad 2010-10-07 06:01:31

+0

然後,您確實必須將模板實現移到標題中。只是想到一個定義規則和所有爵士樂...... – 2010-10-07 06:38:21

2

我相信這是因爲當你編譯c.cpp編譯器不知道它需要爲C::call<Merc>(Merc&)生成代碼,當你正在編譯main.cpp它不具有的C::call<T>(T&)從中定義來實例化C::call<Merc>(Merc&)

模板定義本質上是語義宏,與預處理器的#define詞法宏非常相似,它們必須在使用它們的編譯單元中可見。

0

實質上,你不能在當前C++的單獨文件中擁有相關的模板聲明和定義。你應該在一個文件中完全定義C類。

+0

只是通過澄清:對於公共/受保護模板的常見和已說明的情況而言,這是正確的,但對於專用模板不是必需的。 – 2010-10-07 05:57:01

+0

朋友類和私人模板會發生什麼? – nakiya 2010-10-07 06:06:36

相關問題