可能重复:
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 。任何人都知道如何解决这个问题或如何更好地组织头文件?
答案 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;
output
中Root.h
的情况类似,以及您应该在头文件中声明变量的任何其他地方。