2010-08-03 49 views
0

這對我來說是神祕的。我在Ubuntu使用G ++,這是我的一些代碼(與類名更改,但沒有別的,因爲我仍在使用存根無處不在):未定義的參考與模板類的成員實施

Bob.hpp

template <class A> 
class Bob : public Jack<Chris, A> 
{ 
    public: 

     Bob(int x1, int x2, float x3 = 1.0, float x4 = 2.0, float x5 = 3.0) throw(Exception); 
     virtual ~Bob(); 
}; 

Bob.cpp

template <class A> 
Bob<A>::Bob(int x1, int x2, float x3, float x4, float x5) throw(Exception) 
{ 

} 

template <class A> 
Bob<A>::~Bob() 
{ 

} 

我:我在這樣的另一個文件執行使用這樣的:

的main.cpp

int main() 
{ 
    Bob<Alice> instance(1, 2); 
} 

與編譯:

g++ -c Bob.cpp -o Bob.o 
g++ -c main.cpp -o main.o 
g++ -L"libs" -llib main.o Bob.o prog 

給我 main.o:在功能main': main.cpp:(.text+0x1fd): undefined reference to鮑勃::鮑勃(INT,INT,浮動,浮動,浮動)' collect2:ld返回1退出狀態

我完全難住了。用g ++連接階段改變順序沒有區別。編譯目標文件不會產生任何問題。爲什麼在實現構造函數時使用未定義的引用?如果任何人都可以解釋這一點,這是非常感謝。

+2

請參閱[爲什麼我無法將其聲明中的模板類的定義與其聲明分開並放入.cpp文件中?](http://www.parashift.com/c++-faq-lite/templates.html #faq-35.12)來自C++ FAQ Lite。 – 2010-08-03 19:27:10

+0

@詹姆斯麥克奈利斯:爲什麼不把它作爲答案? :) – 2010-08-03 20:16:31

+1

@Merlyn:我沒有時間寫出高質量的答案,並且一般認爲這是一種糟糕的形式,只是將鏈接發佈到另一個網站作爲答案,而不至少總結鏈接的內容。 – 2010-08-03 20:59:56

回答

1

您需要將代碼從Bob.cpp進入Bob.hpp。當編譯器在Bob.cpp中看到Bob::BobBob::~Bob的定義時,它不知道實際將要實例化的Bob的類型(即Bob<int> vs Bob<SomeClass>並且不生成它們的代碼 或者,您仍然可以放置在Bob.cpp文件中的代碼,但是你需要聲明哪些類型鮑勃將要被實例化,例如: 內Bob.cpp的:

template 
class Bob<Alice>; 
1

類模板成員函數的聲明和定義應該全部在同一個頭文件中。

編譯Bob.cpp時,編譯器同時提供了聲明和定義。此時編譯器不需要爲模板類生成任何定義,因爲沒有實例化。當編譯器編譯main.cpp時,有一個實例化:模板類Bob<Alice>。此時編譯器有聲明但沒有定義!

0

除了其他人提出的問題,圖書館必須在GCC命令行上最後一個。相反的:

g++ -L"libs" -llib main.o Bob.o prog 

你想:

g++ -L"libs" main.o Bob.o prog -llib 
+0

有效的評論,但不是真正的問題答案。我確實知道這一點,順序方式是從另一個修復嘗試中剩下的,我改變了include和鏈接順序。 – TMP 2010-08-04 04:39:52

0

如果你覺得Bob<Alice>構造應是否定義?在Bob.cpp中沒有定義,因爲在Bob.cpp中沒有提及Bob<Alice>。有一個模板,當Bob.cpp被編譯到Bob.o中時,它可能被用來定義Bob<Alice>,但它不是。

將模板定義放入Bob.cpp或Bob36pp中的Bob<Alice>

+0

謝謝你的答案!這很好,很簡潔,所以我會接受它,但其他人有更多的「肉」,值得多一點。 – TMP 2010-08-04 04:41:15