我正在尝试运行一段非常简单的代码。我一直收到链接器错误。我的代码如下所示:
main.cpp -->
#include <iostream>
#include "Complex.h"
using namespace std;
int main()
{
Complex c1(1.0, 5.0); // this should create Complex object 1.0 + i5.0
return 0;
}
复杂.h -->
#include <iostream>
class Complex {
private:
double real;
double imaginary;
public:
Complex(double, double);
void setReal(double);
void setImaginary(double);
};
复杂.cpp -->
#include "Complex.h"
#include <cmath>
Complex::Complex(double x, double y) {
setReal(x);
setImaginary(y);
}
void Complex::setReal(double x) {
real = x;
}
void Complex::setImaginary(double x) {
imaginary = x;
}
我遇到的错误如下所示:
我一直在尝试运行我的主程序,但我一直收到链接器错误。我不知道是什么原因造成的。如果有任何建议,我将不胜感激。
就这样
g++ main-3.cpp complex.cpp
注意文件名 main-3,这与您的问题不一致。
您必须将正在使用的所有 cpp 文件提供给 g++ 命令行,以告诉 g++ header 中定义的函数的代码位于何处。阅读 .o
文件、静态链接并理解其含义。
这是我遵循的一个小指南,用于了解文件包含和其他因素:
C++ 编译非常简单:
- 读取.cpp文件
- 将每个#include 语句替换为指定文件的文本(只需将其转储)
- 如果生成的文本仍然有#include 指令(现在来自头文件),转到第 2 步。
- 将 hughe messy blob 编译成“.o”目标文件,用符号替换对函数的调用,并向该文件添加已知符号表及其定义位置。
- 如果指定了更多 .cpp 文件,则开始一个新的空文本 blob。转到第 1 步。
- 调用链接器“ld”将所有目标文件链接在一起,用实际地址替换符号。
严格来说,以上是当今的谎言,遗漏了很多内容,也没有提到优化。但它仍然是编译器行为的有用指南。
要用它来解释您的错误:
Complex.h
通过 main.cpp
中的 #include
被转储到你的 blob 中,但是 Complex.cpp
没有。 g++ 为您生成了一个内部临时 .o 文件,其中包含类似
的内容
PUT 1.0 on Stack
PUT 5.0 on Stack
JUMP Complex::Complex
... 并使用该 .o 文件运行链接器“ld”。
ld 找不到符号 Complex::Complex 的地址,
它需要一个内存地址才能跳转到。
如果您也编译 Complex.cpp,生成的 Complex.o 将有一个符号表,例如,这个条目:
Complex::Complex = 0xaaff
给定 Complex.o 的链接器现在可以用地址替换 main.o 中的符号。
PUT 1.0 on Stack
PUT 5.0 on Stack
JUMP 0xaaff