为什么即使使用标题保护,我也会收到链接错误?

时间:2013-02-01 09:23:20

标签: c++

  

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

Global.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

Root.h

#ifndef Root_h
#define Root_h

// declarations

OutputHandler *output;

#endif

ROOT.CPP

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

root.obj <已经定义了 exitStatus 静态bool instanceExists 静态类输出的错误/ strong>在 OutputHandler.obj 中。我假设问题是在 Root.h OutputHandler.cpp 中包含头文件 OutputHandler.h 。任何人都知道如何解决这个问题或如何更好地组织头文件?

3 个答案:

答案 0 :(得分:4)

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

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

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

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

解决此问题的最简单方法是永远不要在标题中定义内容,只声明它们。

因此,在标题中(例如xyzzy.h),您有:

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

并且在想要使用它的所有C文件中,放置:

$include "xyzzy.h"

并且,在这些C文件的一个中,也放了:

int xyzzy;        // define it here, once.

您可以将声明视为一个简单的“我声明它存在于某个地方,而不是在这里”,而定义是“我在这里和现在创建它”。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

问题出在连接阶段;在标题中包含警卫不会帮助你。

在C中,有声明定义的单独概念。声明是放入标题的内容;他们只是说存在一个特定的变量。变量的定义是实际为其分配存储的地方。

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

#ifndef Global_h
#define Global_h

#include <iostream>

usigned char exitStatus;

#endif

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

extern char exitStatus;

并且只在一个源文件中,使用以下内容定义

char exitStatus;

outputRoot.h的情况类似,以及您应该在头文件中声明变量的任何其他地方。

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