0

假设我有一个类模板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

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 <- 好的

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

B.hpp

#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让我彻夜难眠,威胁着我的理智。

编辑

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

4

3 回答 3

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.

于 2013-11-05T13:05:57.897 回答
1
  $ g++ -std=c++11 testB.cpp   
  Undefined references to B(), and ~B()

这显然是错误的(我之所以这么说是因为我不明白您为什么要这样做)。您只编译一个翻译单元,它使用在另一个未编译的 (B.cpp) 中定义的符号。

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

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

B::foo();
于 2013-11-05T13:14:45.733 回答
1

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

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

于 2013-11-05T14:41:09.820 回答