【问题标题】:Why am I getting linking errors even with header guards? [duplicate]为什么即使使用标头保护也会出现链接错误? [复制]
【发布时间】:2013-02-01 09:23:20
【问题描述】:

可能重复:
Why does this not prevent multiple function declarations?

全球.h

#ifndef Global_h
#define Global_h

#include <iostream>

unsigned char exitStatus;

#endif

OutputHandler.h

#ifndef OutputHandler_h
#define OutputHandler_h

#include "Global.h"

class OutputHandler {
private:
    static bool instanceExists;
// more code  

#endif

根.h

#ifndef Root_h
#define Root_h

// declarations

OutputHandler *output;

#endif

根.cpp

#include "Root.h"
// gets instance of OutputHandler
// more code

我收到关于 exitStatusstatic bool instanceExistsstatic class output 已由 Root.obj 在 OutputHandler.obj 中。我认为问题在于在 Root.hOutputHandler.cpp 中都包含头文件 OutputHandler.h。有谁知道如何解决这个问题或如何更好地组织头文件?

【问题讨论】:

  • Q 的答案详细解释了原因。简而言之,您不应该在头文件中定义对象,然后将该头包含在多个 TU 中。它违反了 ODR。

标签: c++


【解决方案1】:

因为包含保护仅在翻译单元级别起作用(对于这个简单的情况,您可以将单个 C 文件视为一个翻译单元)。

这意味着单个 C 文件,如果它包含两次头文件,由于包含保护,将不会第二次处理它。

但是,如果您包含来自两个不同 C 文件的标头,每个都将获得该标头中定义的变量的副本。

然后,当您将它们链接在一起时,您会得到重复项。

解决这个问题的最简单方法是永远不要在标题中定义东西,只声明它们。

所以,在标题中(例如,xyzzy.h),你有:

extern int xyzzy;  // declare but don't define.

在所有想要使用它的 C 文件中,输入:

$include "xyzzy.h"

并且,在这些 C 文件的 一个 中,还放入:

int xyzzy;        // define it here, once.

您可以将声明视为简单的“我声明它存在于某处,只是不在这里”,而定义是“我在此时此地创建它”。

【讨论】:

    【解决方案2】:

    Global.h 中声明extern usigned char exitStatus 并在一个 实现文件中定义它。

    【讨论】:

      【解决方案3】:

      问题出在链接阶段;在标题中包含警卫对您没有帮助。

      在 C 中,声明定义这两个概念是分开的。声明是放在标题中的;他们只是声明存在一个特定的变量。变量的定义是实际为它分配存储的地方。

      例如,在您的Global.h 中,您有:

      #ifndef Global_h
      #define Global_h
      
      #include <iostream>
      
      usigned char exitStatus;
      
      #endif
      

      这是定义一个名为exitStatus 的变量,链接器抱怨,因为任何给定的变量只能在程序中的一个位置定义。您需要做的是在标题中声明它,然后在源文件 (*.cpp) 中的一个位置定义它。例如,您的标头应声明 exitStatus:

      extern char exitStatus;
      

      并且仅在一个源文件中,定义它:

      char exitStatus;
      

      Root.h 中的output 的情况与您应该在头文件中声明变量的任何其他位置类似。

      另请参阅:http://www.cprogramming.com/declare_vs_define.html

      【讨论】:

        猜你喜欢
        • 2015-03-08
        • 2021-09-20
        • 1970-01-01
        • 2019-07-27
        • 2020-12-15
        • 2014-04-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-25
        相关资源
        最近更新 更多