假设我有一个类模板A
,而非模板类B
继承自A
。虽然A
编译正常,但编译B
会触发链接器错误。具体地,
#ifndef A_HPP_INCLUDED
#define A_HPP_INCLUDED
template <typename T>
class A {
public:
A();
A(A<T>&& );
virtual ~A();
/* ... */
protected:
T x;
};
#include A.tpp
#endif
#include "A.hpp"
template <typename T>
A<T>::A() { ... }
template <typename T>
A<T>::A(A<T>&& other)
: x(std::move(other.x)) { }
template <typename T>
A<T>::~A() { ... }
#include "A.hpp"
int main() {
A<std::string> a;
/* ... */
return 0;
}
按如下方式编译testA.cpp
成功:
$ g++ -std=c++11 testA.cpp
&lt; - 确定
接下来是继承自class B
的非模板A
:
#ifndef B_HPP_INCLUDED
#define B_HPP_INCLUDED
#include "A.hpp"
class B
: public A<std::string> {
public:
B();
virtual ~B();
static A<std::string> foo();
};
#endif
#include "B.hpp"
B::B()
: A(std::move(foo())) { }
B::~B() { }
A<std::string> B::foo() { ... }
#include "B.hpp"
int main() {
B b;
/* ... */
return 0;
}
testB.cpp
的编译似乎没问题,但链接器不是一个快乐的露营者:
$ g++ -std=c++11 testB.cpp
Undefined references to B(), and ~B()
collect2: error: ld returned 1 exit status
$ g++ -std=c++11 testB.cpp B.cpp
Undefined reference to B.foo()
collect2: error: ld returned 1 exit status
非常感谢任何帮助/想法。 ld
先生大部分时间都让我活了起来,并威胁着我的理智。
谢谢Mike Seymour!这个最小的例子不是真实代码的真实再现,因为在实现中确实缺少一个限定符,并且是装备中的扳手。
答案 0 :(得分:3)
我建议你在两个不同的传递中编译和链接:
g++ -c -std=c++11 -o B.o B.cpp
g++ -c -std=c++11 -o TestB.o TestB.cpp
g++ -o test.exe B.o TestB.o
如果我的建议打破了它至少会清楚哪里缺少什么,你将能够使用nm
调试单个目标文件。
答案 1 :(得分:1)
$ g++ -std=c++11 testB.cpp
Undefined references to B(), and ~B()
这个显然是错的(我只是说,因为我不明白你为什么要这样做)。 您只编译一个翻译单元,它使用另一个(B.cpp)中未编译的符号定义。
我认为您应该在 testB.cpp 中的...
后面发布实际内容,以帮助找到问题。它可能是您使用foo()
预期:由于foo
是您的类的静态成员方法,因此您在测试中的调用应如下所示:
B::foo();
答案 2 :(得分:1)
在您的真实代码中,ParsedData::parsedStream
是一个模板,因此应该在标头中定义,以便它可以在每个可能需要实例化它的翻译单元中使用。
此外,即使在.cpp
文件中也没有定义它,因为您不使用ParsedData::
限定符,而是在命名空间范围内声明了不同的模板。