2010-08-03 58 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