2013-02-01 60 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

相關問題