模板类继承链接器错误

Template class inheritance linker errors

本文关键字:错误 链接 继承      更新时间:2023-10-16

假设我有一个类模板A,非模板类B继承自A。虽然A编译正常,但编译B会触发链接器错误。具体说来

A.hpp

#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

A.tpp

#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() { ... }

测试A.cpp

#include "A.hpp"
int main() {
    A<std::string> a;
    /* ... */
    return 0;
}

如下方式编译testA.cpp成功:

$ g++ -std=c++11 testA.cpp <- 确定

接下来是从A继承的非模板class B

B.马力

#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

B.cpp

#include "B.hpp"
B::B()
    : A(std::move(foo())) { }
B::~B() { }
A<std::string> B::foo() { ... }

测试B.cpp

#include "B.hpp"
int main() {
    B b;
    /* ... */
    return 0;
}

testB.cpp的编译似乎还可以,但链接器不是一个快乐的露营者:

尝试 1

$ g++ -std=c++11 testB.cpp   
Undefined references to B(), and ~B()
collect2: error: ld returned 1 exit status

尝试 2

$ g++ -std=c++11 testB.cpp B.cpp
Undefined reference to B.foo()
collect2: error: ld returned 1 exit status

任何帮助/想法都非常感谢。 先生 ld让我彻夜难眠,并威胁着我的理智。

编辑

谢谢迈克·西摩!这个最小的例子并不是真实代码的真正演绎,因为实现中确实缺少限定符,并且是齿轮中的扳手。

我建议你用两个不同的传递进行编译和链接:

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 调试单个对象文件。

在实际代码中,ParsedData::parsedStream 是一个模板,因此应该在标头中定义,以便它在每个可能需要实例化的翻译单元中都可用。

此外,即使在.cpp文件中也没有定义它,因为您省略了ParsedData::限定符,而是在命名空间范围内声明了不同的模板。

  $ g++ -std=c++11 testB.cpp   
  Undefined references to B(), and ~B()

这个显然是错误的(我只是这么说,因为我不明白你为什么要做这个尝试)。仅编译一个翻译单元,该翻译单元使用在另一个未编译的 (B.cpp) 中定义的符号。

我认为您应该在testB中发布...背后的实际内容.cpp以帮助找到问题。它可能在您使用foo()

通过预期:由于foo是类的静态成员方法,因此您在测试中的调用应如下所示:

B::foo();
相关文章: