2013-02-01 56 views
1

可能重复:
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 

我越来越被已经被OutputHandler定义Root.obj关于退出状态静态布尔instanceExists,并静态类输出错误.obj。我认为问题在于包含头文件OutputHandler.h都在Root.hOutputHandler.cpp。任何人都知道如何解决这个问题或如何更好地组织头文件?

+0

到Q的答案为什么在详细讲解。简而言之,您不应该在头文件中定义对象,然后将该头包含在多个TU中。它违反了ODR。 –

回答

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. 

你可以想想德声明是一个简单的“我声明这存在于某个地方,而不是在这里”,而定义是“我在这里和现在创造这个”。

2

声明extern usigned char exitStatusGlobal.h并定义它在一个执行文件。

1

问题在于链接阶段;在标题中加入警卫不会对你有所帮助。

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

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

#ifndef Global_h 
#define Global_h 

#include <iostream> 

usigned char exitStatus; 

#endif 

定义一个名为exitStatus变量,链接器在抱怨,因为任何给定的变量应该只在一个地方在一个程序中定义。你需要做的是声明它在头,然后定义它只在一个源(* .cpp)文件中的一个地方。例如,你的头应该声明退出状态有:

extern char exitStatus; 

,并在只有一个源文件,定义它:

char exitStatus; 

的情况是在Root.houtput相似,以及作为任何其他地方你应该在头文件中声明变量。

参见:http://www.cprogramming.com/declare_vs_define.html

相关问题