【问题标题】:g++: linker issue on Mac OS X - Undefined symbols for architecture x86_64g++:Mac OS X 上的链接器问题 - 架构 x86_64 的未定义符号
【发布时间】:2015-06-30 22:45:13
【问题描述】:

我在here之前问过这个问题,但没有得到答案,只是“绕道而行”。现在,我正在尝试找到问题的实际解决方案(如下所述)。在有人说之前有人问过这个问题之前,我想说我尝试了herehereherehere 提供的解决方案 - 没有任何帮助:(

问题是链接器说Undefined symbols for architecture x86_64 没有任何其他警告或错误。调用、完整的错误消息和正在编译的代码如下所示。

注意:如果我定义operator<< inline,问题就消失了,但这并不是真正的解决方案,而是绕道:)

提前谢谢你:)

调用和环境

环境:

  • 操作系统:Mac OS X Yosemite (10.10.4)
  • XCode:6.4 (6E35b)
  • uname -a: Darwin wireless1x-XXX-XXX-XXX-XXX.bu.edu 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_6
  • g++ --version: Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.4.0 Thread model: posix

运行参数:

g++ -std=c++11 -lm -stdlib=libc++ tstLinkedList1.cpp -o tstLinkedList1

g++ -std=c++11 -lm -stdlib=libstdc++ tstLinkedList1.cpp -o tstLinkedList1

我也尝试在这两种情况下添加-lc++ - 同样的事情:(

错误

编辑:operator<< 重载中发生错误,它在下面LinkedList.hpp 文件的最末尾定义

使用-stdlib=libc++:

Undefined symbols for architecture x86_64:
  "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, LinkedList<int> const&)", referenced from:
      _main in tstLinkedList1-66598f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

使用-stdlib=libstdc++:

Undefined symbols for architecture x86_64:
  "operator<<(std::ostream&, LinkedList<int> const&)", referenced from:
      _main in tstLinkedList1-8d9300.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

代码

LinkedList.hpp:

#pragma once

template <typename T> class LinkedList;
template <typename T>
std::ostream& operator<<(std::ostream& os, const LinkedList<T>& list);


/** Node class
 * 
 * @tparam T template type
 */
template <typename T>
class Node {
private:
  T _elem;                      //!< Stored value
  Node<T>* _next;               //!< Next element

  friend class LinkedList<T>;   //!< Friend class
};


/** Singly Linked List
 *
 * @tparam T template type
 */
template <typename T>
class LinkedList {
public:
  LinkedList();
  ~LinkedList();
  std::size_t size() const;
  bool empty() const;
  const T& front() const;
  void addFront(const T& e);
  void removeFront();
public:
  // Housekeeping
  friend std::ostream& operator<<(std::ostream& os, const LinkedList<T>& list);
private:
  Node<T>* _head;
  std::size_t _size;
};

/** Constructor */
template <typename T>
LinkedList<T>::LinkedList() : _head(nullptr), _size(0) {}

/** Destructor */
template <typename T>
LinkedList<T>::~LinkedList() {
  while (!empty()) removeFront();
}

/** Number of elements in the list
 * 
 * @returns std::size_t Number of elements in the list
 */
template <typename T>
std::size_t LinkedList<T>::size() const {
  return this->_size;
}

/** Empty?
 *
 * @returns bool True if empty
 */
template <typename T>
bool LinkedList<T>::empty() const {
  return _head == nullptr;
}

/** Get front element (read-only)
 *
 * @returns T
 */
template <typename T>
const T& LinkedList<T>::front() const {
  return _head->_elem;
}

/** Add element in the front of the list
 * 
 * @param e Element to be added
 */
template <typename T>
void LinkedList<T>::addFront(const T& e) {
  Node<T>* v = new Node<T>;
  v->_elem = e;
  v->_next = _head;
  _head = v;
  _size++;
}

/** Remove the first element */
template <typename T>
void LinkedList<T>::removeFront() {
  if (empty()) return;
  Node<T>* old = _head;
  _head = old->_next;
  _size--;
  delete old;
}

/** Operator<< for the linked list
 *
 * @returns std::ostream
 * @param LHS->std::ostream
 * @param RHS->LinkedList<T>
 */
template <typename T>
std::ostream& operator<<(std::ostream& os, const LinkedList<T>& list) {
  os << "TEST";
  return os;
}

tstLinkedList1.cpp:

#include <iostream>
#include "LinkedList.hpp"

using namespace std;

int main() {
  LinkedList<int> ll1;
  ll1.removeFront();
  ll1.addFront(1);

  std::cout << ll1 << std::endl;
}

【问题讨论】:

  • 我们能看到你在哪里定义了“std::ostream& operator& list)”吗?而且你已经编译了 LinkedList cpp,对吧?
  • 当然,我会在问题中进行编辑(最后在LinkedList.hpp中定义

标签: c++ macos c++11 operator-overloading


【解决方案1】:

朋友声明并没有像你想象的那样做。它声明了一个非模板函数,而不是您之前声明的模板。你需要的是:

// within LinkedList:
template<typename U>
friend std::ostream& operator<<(std::ostream&, const LinkedList<U>&);

匹配您声明的模板并让那个成为朋友。嗯,整个模板。或者,您也可以使用

// within LinkedList:
friend std::ostream& operator<<<>(std::ostream&, const LinkedList&);
// NOTE:                       ^^ here you need to add <>

T 的朋友(您可以使用LinkedList 代替LinkedList&lt;T&gt; - 在课堂上没有什么不同)。

如果你只使用

// within LinkedList:
friend std::ostream& operator<<(std::ostream&, const LinkedList<T>&);

你需要有

// within the global namespace
// NOTE: not a template!
std::ostream& operator<<(std::ostream&, const LinkedList<int>&);

使您的示例工作。或者你可以定义朋友operator&lt;&lt; inline:

// within LinkedList:
friend std::ostream& operator<<(std::ostream& os, const LinkedList<T>& list)
{
    // implement me!
    return os;
}

并完全删除前向声明。

【讨论】:

  • 非常感谢您的解释-我尝试了两种方法-template &lt;typename U&gt;operator&lt;&lt;&lt;&gt;-它们都有效。我没有尝试inline 解决方案 - 到目前为止我是如何使用它的。非常感谢您的解释! :)
猜你喜欢
  • 2012-04-26
  • 2017-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
相关资源
最近更新 更多