【问题标题】:Linker error when including header in files other than main.cpp在 main.cpp 以外的文件中包含标头时出现链接器错误
【发布时间】:2017-03-31 15:00:39
【问题描述】:

我正在尝试将一些实用程序函数和全局变量添加到我的代码中,这样我就可以在项目中我想要的每个类中使用它们。我想使用 .hpp 文件进行定义,使用 .cpp 文件进行实施。

这是这两个文件的摘要:

// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp


namespace utils {

    int global_variable1;

    int global_variable2;

    void utility_function1(...);

    void utility_function2(...);

    void utility_function3(...);
}

#endif /* utilities_hpp */

和实施:

// This is Utilities.cpp
#include "Utilities.hpp"


namespace utils {

    void utility_function1(...) {
        // Some code
    }


    void utility_function2(...) {
        // Some code
    }


    void utility_function3(...) {
        // Some code
    }

}

除了我的main.cpp 文件之外,我还有另外两个课程。我的 main.cpp 文件包含 Class1.hpp 标头,其中包含 Class2.hpp 标头。

现在我认为我可以在Class1.hppClass2.hpp 中添加另一个#include "Utilities.hpp" 而不会出现任何问题,因为我在该标题中使用了防护。问题是,当我尝试这样做时,链接器会向我抛出此错误:Apple Mach-O Linker (ld) Error Group - clang: error: linker command failed with exit code 1 (use -v to see invocation),我不明白为什么或如何解决它。

我在 macOS Sierra 10.12.4 上使用 Xcode 8.3。

我希望我能够解释我的问题,非常感谢你们。

【问题讨论】:

  • 它是否提供更详细的输出?另外,请尝试清理并重建您的项目。

标签: c++ xcode linker


【解决方案1】:

您违反了单一定义规则。 global_variable1global_variable2 应在标题中声明为 extern 并在一个翻译单元中定义(可能是 Utilities.cpp)。

您在包含在多个翻译单元中的标头中定义了全局变量,因此在 main.cpp 中定义了一个 utils::global_variable1,在 Utilities.cpp 中定义了一个。当涉及到链接时间时,链接器无法知道使用哪个global_variable1,所以会抛出错误。

要修复它,请将extern 关键字添加到您的声明中,并在“Utilities.cpp”中添加定义:

Utilities.hpp:

// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp


namespace utils {

    extern int global_variable1;
  //^^^^^^ <-----HERE
    extern int global_variable2;
  //^^^^^^ <-----HERE
    void utility_function1(...);

    void utility_function2(...);

    void utility_function3(...);
}

#endif /* utilities_hpp */

Utilities.cpp:

// This is Utilities.cpp
#include "Utilities.hpp"

namespace utils {

    int global_variable1;  //<---- Definitions added
    int global_variable2;

    void utility_function1(...) {
        // Some code
    }

    void utility_function2(...) {
        // Some code
    }

    void utility_function3(...) {
        // Some code
    }
}

【讨论】:

  • 非常感谢!!!但是你能解释一下为什么会发生这种情况吗?我认为使用#ifndef utilities_hpp #define utilities_hpp #endif 保护措施可以防止出现此类问题
  • #ifndef 包含守卫防止标头在在单个翻译单元中被包含多次
  • 哦,所以您是说我的标头已包含在多个.cpp 文件中,因此我的全局变量已被多次声明。我说的对吗?
  • 正确。虽然问题不在于变量被声明多次,而是它们被定义多次。
  • 我明白了。非常感谢!
【解决方案2】:

您在标题中的全局变量上缺少 extern 关键字。因此,您正在定义它们,当您将标头包含在两个不同的源模块中时,这会导致多个定义。

在头文件 (extern int global_variable1;) 中添加 extern 后,您需要在 .cpp 文件中添加定义,并在其中定义函数。

【讨论】:

    猜你喜欢
    • 2022-06-11
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 2020-03-11
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多