ld:在 OSX 10.9 上找不到体系结构 x86_64 的符号
ld: symbol(s) not found for architecture x86_64 on OSX 10.9
我正在我的 Xcode 6.2 上执行 C++ 程序,但出现此错误:
Undefined symbols for architecture x86_64:
"operator+(Stack1<int> const&, Stack1<int> const&)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我不确定如何继续解决这个问题,我在 whosebug.com 上检查了几个其他人但无法解决我的问题,
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Stack1;
template <class T>
Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y) {
Stack1<T> z = x;
for (unsigned int i=x.size(); i<(x.size()+y.size()); i++) {
z.push(y[i]);
}
return z;
}
template <class T>
class Stack1 {
friend Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y);
private: vector <T> elems;
public: bool empty();
void push(const T &item);
T & top();
void pop();
long size();
};
template <class T>
bool Stack1<T>::empty() {
return elems.empty();
}
template <class T>
void Stack1<T>::push(const T &item){
elems.push_back(item);
}
template <class T>
T &Stack1<T>::top(){
return elems.back();
}
template <class T>
void Stack1<T>::pop() {
if (!elems.empty())
return elems.pop_back();
}
template <class T>
long Stack1<T>::size() {
return elems.size();
}
int main(int argc, const char * argv[]) {
Stack1 <int> intStack;
Stack1 <float> floatStack;
Stack1 <string> stringStack;
Stack1 <int> a;
Stack1 <int> b;
intStack.push(7);
intStack.push(3);
intStack.push(0);
intStack.push(8);
floatStack.push(0.9);
floatStack.push(4.78);
floatStack.push(2.157);
stringStack.push("test1");
stringStack.push("abc");
while (!intStack.empty()) {
cout << "Popping from intStack: " << intStack.top() << endl;
intStack.pop();
}
if (intStack.empty()) {
cout << "intStack is empty" << endl;
}
while (!floatStack.empty()) {
cout << "Popping from intStack: " << floatStack.top() << endl;
floatStack.pop();
}
if (floatStack.empty()) {
cout << "floatStack is empty" << endl;
}
while (!stringStack.empty()) {
cout << "Popping from intStack: " << stringStack.top() << endl;
stringStack.pop();
}
if (stringStack.empty()) {
cout << "stringStack is empty" << endl;
}
for (int i=0; i<3; i++) {
a.push(i);
}
for (int i=9; i>5; i--) {
b.push(i);
}
// cout << "Size of a:" << a.size();
Stack1 <int> c;
c = a+b;
while (!c.empty()) {
cout << "Popping from c: " << c.top() << endl;
c.pop();
}
return 0;
}
得到这个错误:
error: failed to launch '/Users/User-name/Library/Developer/Xcode/DerivedData/4_TemplatedStack-bmcfhzdrgyhhybajmxvpyuypgmag/Build/Products/Debug/4_TemplatedStack'
评论中提到的问题是指您代码中的一个危险错误,但与链接器问题无关。您需要做的是在 operator+
:
之后添加 <>
friend Stack1<T> & operator+ <>(const Stack1<T> &x, const Stack1<T> &y);
然后,long size()
需要是 const
如果你想在 const
个对象上调用它。
总之。请阅读this guide on operator overloading。 operator+
不应该 return 引用,尤其是局部变量。如果有的话,它的 return 值应该是 const T
。还有其他问题,但我将其作为练习留给您。
要补充其他答案,由于模板和模板实例化的工作方式,单独定义和声明模板通常没有意义,因为您的定义需要进入 header文件无论如何,以允许它被实例化。通常,声明和定义是分开的,因此声明位于 header 文件中,而定义位于源文件中,这提供了两个好处:1.) 库的用户只需要 header 和编译后的源代码,因此将它们分开可以加快开发速度(通过使用 pre-compiled 库)2.) 在开源之外,有时可能会隐藏实现代码,因此只有 header分散式。然而,当涉及到模板时,为了实例化模板,定义和声明都是必需的。因此,只需将声明和定义组合在一起,您就可以避免大量的样板代码和语法烦恼:
// stack1.h
#ifndef STACK1_H
#define STACK1_H
#include <vector>
template<typename T> class Stack1 {
public:
Stack1() {}
Stack1(const Stack1& o) : elements_(o.elements_) {}
Stack1(const std::vector<T>& elements) : elements_(elements) {}
virtual ~Stack1() {}
Stack1 operator+(const Stack1& o) const {
return Stack1(elements_ + o.elements_);
}
void push(const T& item) { elements_.push_back(item); }
bool empty() const { return elements_.empty(); }
T top() const { return elements_.back(); }
size_t size() const { return elements_.size(); }
private:
std::vector<T> elements_;
};
#endif
虽然,当定义和声明分开时,可以为模板正确指定定义语法,但这样做要容易得多。如果您确实继续将定义和声明分开,除了其他建议之外,您还需要为您的定义使用 "inline" 关键字,以防止在将定义放入时 one-definition-rule 违规a header(根据使用来自多个源文件的模板的需要)。
您为 operator +
、
定义的函数存在几个问题
你在这里定义
template <class T>
Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y)
说
operator+
是一个模板函数,但在 Stack1
的 class 定义中,您说的是
friend Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y);
不是模板函数,这是 link 错误的原因。解决方案在 Stack1
内更改为
friend Stack1<T> operator+ <>(const Stack1<T> &x, const Stack1<T> &y);
,
详细解释在isocpp FAQ.
请注意,您正在返回引用 Stack1<T> & operator+
,但在函数体内您有 return z
,其中 z
是局部变量,一旦函数调用完成,z
被销毁,对它的引用将是灾难性的。
你需要改变
for(unsigned int i=x.size(); i<(x.size()+y.size()); i++)
到
for(unsigned int i=0; i<y.size(); i++)
因为你推 y[i]
并且 i
不能大于 y.size()
.
您还需要为 class Stack1
重载运算符 []
。
我正在我的 Xcode 6.2 上执行 C++ 程序,但出现此错误:
Undefined symbols for architecture x86_64:
"operator+(Stack1<int> const&, Stack1<int> const&)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我不确定如何继续解决这个问题,我在 whosebug.com 上检查了几个其他人但无法解决我的问题,
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Stack1;
template <class T>
Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y) {
Stack1<T> z = x;
for (unsigned int i=x.size(); i<(x.size()+y.size()); i++) {
z.push(y[i]);
}
return z;
}
template <class T>
class Stack1 {
friend Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y);
private: vector <T> elems;
public: bool empty();
void push(const T &item);
T & top();
void pop();
long size();
};
template <class T>
bool Stack1<T>::empty() {
return elems.empty();
}
template <class T>
void Stack1<T>::push(const T &item){
elems.push_back(item);
}
template <class T>
T &Stack1<T>::top(){
return elems.back();
}
template <class T>
void Stack1<T>::pop() {
if (!elems.empty())
return elems.pop_back();
}
template <class T>
long Stack1<T>::size() {
return elems.size();
}
int main(int argc, const char * argv[]) {
Stack1 <int> intStack;
Stack1 <float> floatStack;
Stack1 <string> stringStack;
Stack1 <int> a;
Stack1 <int> b;
intStack.push(7);
intStack.push(3);
intStack.push(0);
intStack.push(8);
floatStack.push(0.9);
floatStack.push(4.78);
floatStack.push(2.157);
stringStack.push("test1");
stringStack.push("abc");
while (!intStack.empty()) {
cout << "Popping from intStack: " << intStack.top() << endl;
intStack.pop();
}
if (intStack.empty()) {
cout << "intStack is empty" << endl;
}
while (!floatStack.empty()) {
cout << "Popping from intStack: " << floatStack.top() << endl;
floatStack.pop();
}
if (floatStack.empty()) {
cout << "floatStack is empty" << endl;
}
while (!stringStack.empty()) {
cout << "Popping from intStack: " << stringStack.top() << endl;
stringStack.pop();
}
if (stringStack.empty()) {
cout << "stringStack is empty" << endl;
}
for (int i=0; i<3; i++) {
a.push(i);
}
for (int i=9; i>5; i--) {
b.push(i);
}
// cout << "Size of a:" << a.size();
Stack1 <int> c;
c = a+b;
while (!c.empty()) {
cout << "Popping from c: " << c.top() << endl;
c.pop();
}
return 0;
}
得到这个错误:
error: failed to launch '/Users/User-name/Library/Developer/Xcode/DerivedData/4_TemplatedStack-bmcfhzdrgyhhybajmxvpyuypgmag/Build/Products/Debug/4_TemplatedStack'
评论中提到的问题是指您代码中的一个危险错误,但与链接器问题无关。您需要做的是在 operator+
:
<>
friend Stack1<T> & operator+ <>(const Stack1<T> &x, const Stack1<T> &y);
然后,long size()
需要是 const
如果你想在 const
个对象上调用它。
总之。请阅读this guide on operator overloading。 operator+
不应该 return 引用,尤其是局部变量。如果有的话,它的 return 值应该是 const T
。还有其他问题,但我将其作为练习留给您。
要补充其他答案,由于模板和模板实例化的工作方式,单独定义和声明模板通常没有意义,因为您的定义需要进入 header文件无论如何,以允许它被实例化。通常,声明和定义是分开的,因此声明位于 header 文件中,而定义位于源文件中,这提供了两个好处:1.) 库的用户只需要 header 和编译后的源代码,因此将它们分开可以加快开发速度(通过使用 pre-compiled 库)2.) 在开源之外,有时可能会隐藏实现代码,因此只有 header分散式。然而,当涉及到模板时,为了实例化模板,定义和声明都是必需的。因此,只需将声明和定义组合在一起,您就可以避免大量的样板代码和语法烦恼:
// stack1.h
#ifndef STACK1_H
#define STACK1_H
#include <vector>
template<typename T> class Stack1 {
public:
Stack1() {}
Stack1(const Stack1& o) : elements_(o.elements_) {}
Stack1(const std::vector<T>& elements) : elements_(elements) {}
virtual ~Stack1() {}
Stack1 operator+(const Stack1& o) const {
return Stack1(elements_ + o.elements_);
}
void push(const T& item) { elements_.push_back(item); }
bool empty() const { return elements_.empty(); }
T top() const { return elements_.back(); }
size_t size() const { return elements_.size(); }
private:
std::vector<T> elements_;
};
#endif
虽然,当定义和声明分开时,可以为模板正确指定定义语法,但这样做要容易得多。如果您确实继续将定义和声明分开,除了其他建议之外,您还需要为您的定义使用 "inline" 关键字,以防止在将定义放入时 one-definition-rule 违规a header(根据使用来自多个源文件的模板的需要)。
您为 operator +
、
你在这里定义
template <class T> Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y)
说operator+
是一个模板函数,但在Stack1
的 class 定义中,您说的是friend Stack1<T> & operator+(const Stack1<T> &x, const Stack1<T> &y);
不是模板函数,这是 link 错误的原因。解决方案在Stack1
内更改为friend Stack1<T> operator+ <>(const Stack1<T> &x, const Stack1<T> &y);
, 详细解释在isocpp FAQ.请注意,您正在返回引用
Stack1<T> & operator+
,但在函数体内您有return z
,其中z
是局部变量,一旦函数调用完成,z
被销毁,对它的引用将是灾难性的。你需要改变
for(unsigned int i=x.size(); i<(x.size()+y.size()); i++)
到for(unsigned int i=0; i<y.size(); i++)
因为你推y[i]
并且i
不能大于y.size()
.您还需要为 class
Stack1
重载运算符[]
。