2012-12-31 133 views
0

內general.h中如何避免鏈接錯誤

#ifndef GENERAL 
#define GENERAL 
namespace counternamespace{ 
    int upperbound; 
    int lowerbound; 
} 
#endif 

內Analyzer.h

#ifndef ANALYZER 
#define ANALYZER 
#include"General.h" 

class Analyzer 
{ 
public : 
    int var ; 
    int func(); 
}; 
#endif 

內Test.h

#ifndef TEST 
#define TEST 
#include"Analyzer.h" //Error 
class Test2 
{ 
public: 
    Test2(void); 

public: 
    ~Test2(void); 
}; 
#endif 

在上面的代碼時,我不在Test.h裏面加分析器一切正常。但添加後顯示以下鏈接器錯誤。

1>Test2.obj : error LNK2005: "int counternamespace::lowerbound" ([email protected]@@3HA) already defined in Analyzer.obj 
2>Test2.obj : error LNK2005: "int counternamespace::upperbound" ([email protected]@@3HA) already defined in Analyzer.obj 

我已經加入了#ifndef/#endif。那麼我在哪裏做錯了?任何人都可以讓我知道嗎?

回答

1
Inside General.h 

#ifndef GENERAL 
#define GENERAL 
namespace counternamespace{ 
    extern int upperbound; 
    extern int lowerbound; 
} 
#endif 

Inside General.cpp 

#include"General.h" 
using namespace counternamespace ; 
int counternamepace::upperbound = 12; 
int counternamepace::lowerbound = 12; 

然後做任何需要的。

1

你不應該在頭文件中定義任何變量。
在每個翻譯單元中創建變量的副本當您將頭文件包含在其他文件中時,因此違反了一個定義規則並導致鏈接錯誤。

+0

:好的。留下Test2.h文件。 Analyzer.h內部也包含了一般的.h文件。因此,在這種情況下,由於分析器和通用轉換單元中的名稱空間定義,應該存在一些鏈接器錯誤。但它沒有顯示任何鏈接器錯誤。你能澄清一下嗎? – Kenta

+0

@Learner你有Analyser.cpp和Test2.cpp,兩者都是不同的編譯單元。 –

+1

我已在此解決方案中添加了詳細信息,並在我的答案中添加了解決方案。 –

2

是的,Alok有權利。你大概有Analyser.cpp和Test2.cpp,都是不同的編譯單元。當你打電話

g++ Analyser.cpp Test2.cpp 

編譯器實際上使Analyser.obj和Test2.obj分開並將它們鏈接在一起。 當編譯器試圖將Analyser.obj和Test2.obj鏈接在一起時,它意識到Test2.obj中的兩個變量也存在於Analyser.obj中。

#define指令不工作,因爲它們只存在於一個單一的編譯單元,所以general.h中包含在Analyser.obj和Test2.obj都

爲了避免這種重複,the solution is wrapping your namespace variables圍繞着一個函數。它是這樣的:

內general.h中

#ifndef GENERAL 
#define GENERAL 
namespace counternamespace{ 
    int& upperbound(); 
    int& lowerbound(); 
} 
#endif 

內General.cpp

#include "General.h" 
namespace counternamespace{ 
    int& upperbound(){static int local; return local;} 
    int& lowerbound(){static int local; return local;} 
} 

因此可以這樣說,現在

counternamespace::upperbound()=3; 
counternamespace::lowerbound()=1; 

,這意味着和你一樣本來會說

counternamespace::upperbound = 3; 
counternamespace::lowerbound = 1; 

不用擔心,編譯器會優化掉函數調用,所以也沒有開銷。

+0

謝謝現在錯誤消失了。但是我如何訪問Analyzer內的counternamespace,我現在無法訪問counternamespace。 – Kenta

+1

@Learner:你可以像以前一樣訪問'counternamespace'。 「upperbound」和「lowerbound」之後的附加括號除外,沒有任何變化。 –