2011-08-17 86 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; 
}