【问题标题】:C++ simple files compilation using "gcc" compiler使用“gcc”编译器编译 C++ 简单文件
【发布时间】:2012-03-21 00:21:06
【问题描述】:

我正在尝试编译一个非常简单的 c++ 代码并根据 gcc 参数的顺序得到一个链接错误。谁能解释这两个命令行行之间有什么区别?

// 这很好用

gcc -x c++ -c *.h *.cpp (first I pass *.h files then *.cpp)
gcc -lstdc++ *.o -o exe

// 这会报错

gcc -x c++ -c *.cpp *.h (first I pass *.cpp files then *.h) 
gcc -lstdc++ *.o -o exe

gcc 是否关心参数顺序?

例子:

// 这个案例很好用

[karen@linux40 ~/C++]$ ls Employee.cpp Employee.h Main.cpp [karen@linux40 ~/C++]$ gcc -x c++ -c *.h *.cpp [karen@linux40 ~/C++]$ ls Employee.cpp Employee.h Employee.o Main.cpp Main.o Makefile [karen@linux40 ~/C++]$ gcc -lstdc++ *.o -o exe [karen@linux40 ~/C++]$ ls exe Employee.cpp Employee.h Employee.o Main.cpp Main.o

// 这是有问题的案例

[karen@linux40 ~/C++]$ ls Employee.cpp Employee.h Main.cpp [karen@linux40 ~/C++]$ gcc -x c++ -c *.cpp *.h [karen@linux40 ~/C++]$ ls Employee.cpp Employee.h Employee.o Main.cpp Main.o [karen@linux40 ~/C++]$ gcc -lstdc++ *.o -o exe Main.o:在函数“main”中: Main.cpp:(.text+0x8d): undefined reference to `Employee::Employee()' collect2: ld 返回 1 个退出状态

员工.h

#include <iostream>
#include <string>
using namespace std;

class Employee {
public:
    Employee();
    Employee(string theName, float thePayRate);

    string getName() const;
    float getPayRate() const;

    float pay(float hoursWorked) const;

protected:
    string name;
    float payRate;
};

员工.cpp

#include "Employee.h"

Employee::Employee() {
}

Employee::Employee(string theName, float thePayRate) {
    name = theName;
    payRate = thePayRate;
}

string Employee::getName() const {
    return name;
}

float Employee::getPayRate() const {
    return payRate;
}

float Employee::pay(float hoursWorked) const {
    return hoursWorked * payRate;
}

Main.cpp

#include "Employee.h"

int main() {
    Employee e;
    return 0;
}

【问题讨论】:

  • 您不应将 .h 文件传递​​给 gcc。
  • “错误”是什么?此外,您的 *.h 文件中有哪些必须明确提供给编译器的内容?
  • 是的,它确实关心链接库的顺序,即使这与您的错误不完全相关,但与您的问题有点相关
  • 是的,我同意你的看法。我不需要传递“.h”文件。但是为什么当我们首先传递“.h”然后是“.cpp”文件时,gcc 感觉找到了,反之亦然?要查看错误消息,请查看我的更新数据。谢谢,凯伦

标签: c++ gcc static-linking


【解决方案1】:

我假设提问者在非标准位置使用标头,因此将它们显式传递给编译器。如果 *.c 中的代码需要 *.h 才能工作,那么在代码之后传入标头将给出错误,而相反的顺序则不会。

如果您在

中包含标题
#include <file.h>

编译器不会在当前目录中找到它们(除非你将代码保存在 /usr/include...),所以使用

#include "file.h"

而不是与代码位于同一目录中的标头。如果它们在其他地方,请添加

-I /path/to/headers/

到 gcc 命令。

祝你好运!

【讨论】:

  • 请看我附上的代码。实际上我使用了“”而不是谢谢凯伦
  • 那么,您的标头是否与您的代码位于同一目录中?如果是这样,完全不使用“*.h”应该可以正常工作。
  • 是的,完全正确!它们在同一个目录中。我已经更新了问题描述,在那里你可以看到 shell 命令“ls”的结果,这表明我在同一个目录中有三个文件。感谢您对我感兴趣并尝试帮助我。
  • 我已经编译了你的代码,如果我把'.h'放在命令的末尾,我会得到和你一样的错误。之前的回答者已经解释了它失败的原因,但要让它工作,你只需要完全省略'.h':'gcc -x c++ -c *.cpp'。
【解决方案2】:

通常你不应该将 .h 文件直接传递给编译器。这没有任何意义,也不正确。

但看起来这里的问题主要是为了了解 gcc 的工作原理。所以我的回答是从这个角度来的。

我假设您在 .cpp 文件中包含相同的 .h 文件。

当您先传递 .cpp 然后传递 .h 时会发生什么,编译器会看到一个声明,然后是定义,然后又是一个声明。这会导致链接器错误,因为第二个声明没有相应的定义。

相比之下,如果你先传递 .h 然后传递 .cpp,它会看到两个声明,然后是定义,这可以很好地链接。

【讨论】:

  • @CollinHockey 这是一个蹩脚的评论,太糟糕了,我们不能对 cme​​ts 投反对票。我认为 grigy 很有礼貌...(+1) 来纠正这个问题。
  • 很合乎逻辑的解释......谢谢你,凯伦
猜你喜欢
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-10
相关资源
最近更新 更多