2011-08-17 67 views
0

只是一個非常小的程序來測試如何使用命名空間。我將它分成3個文件,因爲在大型產品中,ns.h是命名空間接口,ns.cpp是實現。我不能把所有這些東西放到一個文件中。命名空間未定義或重新定義,爲什麼?

下面是代碼:

//ns.h 
#ifndef MY_H 
#define MY_H 
namespace my 
{ 
    int a=1; 
    int b=0; 
    void test(); 
} 
#endif 

//ns.cpp 
#include <iostream> 
#include "ns.h" 

using namespace my; 
//my::a=1; 
//my::b=0; 
void my::test() 
{ 
    std::cout<<a<<std::endl; 
} 

//testns.cpp 
#include <iostream> 
#include "ns.h" 
int main() 
{ 
    std::cout<<my::b<<std::endl; 
    my::test(); 
} 

如果我把上面的代碼,並編譯將獲得:

testns.obj : error LNK2005: "int my::b" ([email protected]@@3HA) already defined in ns.obj 
testns.obj : error LNK2005: "int my::a" ([email protected]@@3HA) already defined in ns.obj 

如果我評論的聲明的#include 「ns.h」 我會得到未定義的錯誤。

D:\mfc\testns.cpp(5) : error C2653: 'my' : is not a class or namespace name 
D:\mfc\testns.cpp(5) : error C2065: 'b' : undeclared identifier 
D:\mfc\testns.cpp(6) : error C2653: 'my' : is not a class or namespace name 
D:\mfc\testns.cpp(6) : error C2065: 'test' : undeclared identifier 

請幫助我,如果你知道如何做到這一點。非常感謝。

回答

2

標題是用於聲明,而不是定義。這與命名空間問題無關。

//ns.h 
#ifndef MY_H 
#define MY_H 
namespace my 
{ 
    extern int a, b; // declared, not defined thanks to 'extern'. 
    void test(); 
} 
#endif 

//ns.cpp 
#include <iostream> 
#include "ns.h" 

int my::a=1; // now we provide the actual definitions. 
int my::b=0; 
void my::test() 
{ 
    std::cout << my::a << std::endl; 
} 

//testns.cpp 
#include <iostream> 
#include "ns.h" 
int main() 
{ 
    std::cout << my::b << std::endl; 
    my::test(); 
} 
+0

是的,它以這種方式工作,但爲什麼我必須在cpp文件中使用my ::?如果包裝很大,這會帶來很多額外的工作。任何意見? – shangping

+0

我只是這樣做的例子。 'using namespace my;'在'ns.cpp'中沒有幫助,因爲這只是說「如果在這裏找不到它們,就試着在'my'中查找名字。它不會說「如果我定義了一些新的東西,我希望它成爲」我的「的一部分。但你可以改爲寫'namespace my {int a = 1; int b = 0; void test()...}'。在'testns。cpp'當然你可以'使用命名空間my',或者'也可以'使用my :: b;使用my :: test'。 –

+0

謝謝Karl,這真的很有道理。很好的答案!最後一種方式是我正在尋找的整潔方式!由於很多時候,人們可能會編寫一些代碼,我不想爲它們添加許多前綴。 – shangping

1

在頭文件中定義變量不是標準做法;它們會在您每次使用#include標題時重新定義,導致您看到的鏈接器錯誤。

如果您需要共享的源文件之間的變量(而且也很少有很好的理由),那麼你應該聲明他們作爲extern在頭文件,然後定義他們在源文件中的一個。

+0

我想這之前,我張貼的問題。它也給出了未定義的錯誤。 – shangping

+0

是的,我知道我應該在cpp文件中添加my :: a,my :: b,即使我有使用命名空間my的語句;這是爲什麼? – shangping

+0

這個答案也是正確的,但我怎樣才能同時批准兩個答案?謝謝! – shangping

2

你在ns.h定義的兩個變量ab,然後頭文件被包含在兩個源文件。這違反了one definition rule,因爲變量現在在包括ns.h的翻譯單元中定義。

你需要做的是在頭聲明變量和在一個源文件中定義他們。

要解決該問題,改變ns.h

#ifndef MY_H 
#define MY_H 
namespace my 
{ 
    extern int a; 
    extern int b; 
    void test(); 
} 
#endif 

ns.cpp

#include <iostream> 
#include "ns.h" 

using namespace my; 

int my::a=1; 

int my::b=0; 

void my::test() 
{ 
    std::cout<<a<<std::endl; 
}