【问题标题】:linker command failed with exit code 1 when link object files链接目标文件时,链接器命令失败,退出代码为 1
【发布时间】:2016-07-25 06:04:36
【问题描述】:

我正在尝试测试 Micheal T. Goodrich 等人在“C++ 中的数据结构和算法”中的单链表示例。我添加了一些作者省略的细节以使其可运行。

代码如下:

#ifndef S_LINKED_LIST
#define S_LINKED_LIST

template <typename E>
class SLinkedList;

template <typename E>
class SNode
{
    private:
        E elem;
        SNode<E> * next;
        friend class SLinkedList<E>;
};
template <typename E>
class SLinkedList
{
    private:
        SNode<E> * head;
    public:
        SLinkedList();
        ~SLinkedList();
        bool empty() const;
        const E& front() const;
        void addFront(const E& e);
        void removeFront();
};
#endif /*SLinkedList.h*/

实施:

#include "SLinkedList.h"
#include <iostream>

template <typename E>
SLinkedList<E>::SLinkedList():head(NULL){}

template <typename E>
SLinkedList<E>::~SLinkedList()
{while(!empty()) removeFront();}

template <typename E>
bool SLinkedList<E>::empty() const
{return head == NULL;}

template <typename E>
const E& SLinkedList<E>::front() const
{return head->elem;}

template <typename E>
void SLinkedList<E>::addFront(const E& e)
{   
    SNode<E> * newNode = new SNode<E>;
    newNode->elem = e;
    newNode->next = head;
    head = newNode;
}

template <typename E>
void SLinkedList<E>::removeFront()
{
    SNode<E> * old = head;
    head = old->next;
    delete old;
}/*SLinkedList.cpp*/

测试文件:

#include <iostream>
#include "SLinkedList.h"

int main()
{
    SLinkedList<std::string> newlist;
    newlist.addFront("MSP");
    std::cout << newlist.front();
    return 0;
}/*test_slinkedlist.cpp*/

运行g++ -c SLinkedList.cppg++ -c test_slinkedlist.cpp 后 我得到目标文件SLinkedList.otest_slinkedlist.o 没有错误。 但是当我运行 g++ -o result test_slinkedlist.o SLinkedList.o 时,我得到了链接器错误:

Undefined symbols for architecture x86_64:
...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我花了一天时间调试这个链接器问题,但找不到。我怀疑这很明显。

操作系统:OS X


完整的错误信息:

Undefined symbols for architecture x86_64:
  "SLinkedList<std::__1::basic_string<char,     std::__1::char_traits<char>, std::__1::allocator<char> >     >::addFront(std::__1::basic_string<char, std::__1::char_traits<char>,     std::__1::allocator<char> > const&)", referenced from:
      _main in test_slinkedlist.o
  "SLinkedList<std::__1::basic_string<char,     std::__1::char_traits<char>, std::__1::allocator<char> > >::SLinkedList()",     referenced from:
      _main in test_slinkedlist.o
  "SLinkedList<std::__1::basic_string<char,     std::__1::char_traits<char>, std::__1::allocator<char> >     >::~SLinkedList()", referenced from:
      _main in test_slinkedlist.o
  "SLinkedList<std::__1::basic_string<char,     std::__1::char_traits<char>, std::__1::allocator<char> > >::front() const",     referenced from:
      _main in test_slinkedlist.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

【问题讨论】:

  • @Revolver_Ocelot 我可以看到你说它是重复的原因,但我认为它可能对像我这样从 C 切换到 C++ 并从 C 继承习惯并且不知道什么关键词的人有所帮助搜索以获取此问题和您的评论,以了解下一步该去哪里。感谢您的建议。

标签: c++ linked-list linker


【解决方案1】:

实施:

你没说,但我们可以假设实现在SLinkedList.cpp

Undefined symbols for architecture x86_64:
...

... 中,您省略了错误消息中最重要的部分。但是,我们可以猜测SLinkedList&lt;std::string&gt;::addFront(...) 是未解析的符号之一。

你的问题是模板方法的body(即实现)必须出现在它所在的每个编译单元中使用过,并且您将此主体放入单独的.cpp 文件中违反了该规则,编译器在编译test_slinkedlist.cpp可见。

这就是为什么模板主体最常包含在SLinkedList.h 中的原因(注意.h,而不是.cpp)。另见this answer

附:从技术上讲,上面的“必须”是不正确的:您还可以使用显式实例化来使编译器生成您需要的模板方法体。但这比将实现放入 .h 文件更高级一些。

【讨论】:

    【解决方案2】:

    在 C++ 中,您不能将未实例化的模板作为单独的编译单元进行编译和链接。

    SLinkedList.cpp 没有实例化模板,因此它基本上不会编译。

    这就是为什么只有模板的库总是只有头文件的原因。

    你有几个选择。

    要么在其中实例化你的 SLinkedList SLinkedList.cpp 的编译单元,让编译器为模板实例生成实际代码,或者将你的头文件和 cpp 合并到一个文件中。

    【讨论】:

      猜你喜欢
      • 2016-04-20
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      • 2015-08-06
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多