虽然很多程序员都熟悉名字空间的概念,但他们常常都是被动地使用名字空间。也就是说他们使用的是第三方定义的成员(如标准库的类和函数),而不是在名字空间中声明自己的类和函数。本文拟讨论如何在名字空间中声明自己的类和函数,以及如何在程序中使用它们。
名字空间是一个范畴,它包含类声明,函数声明,常量声明和模板声明等名字空间成员。例如:
namespace proj_alpha
{
//下面是名字空间 proj_alpha 的成员
class Spy {/*..*/};
void encrypt (char *msg);
const int MAX_SPIES = 8;
}
在上面的例子中,类Spy在一个单独的文件中实现。通常,你是在一个专门的头文件中声明一个类并在不同的源文件中独立地定义其成员函数。那么如何将名字空间成员类分离成多个源文件呢?
下面是名为 Foo.hpp 的头文件,其中定义了一个名为NS的名字空间,它包含类Foo的声明:
//Foo.hpp
namespace NS
{
class Foo
{
public:
void f();
void g();
};
}//close NS
另外,在一个单独的源文件Foo.cpp中,首先包含头文件Foo.hpp以便实现类Foo的成员函数f()和g():
//Foo.cpp
#include "Foo.hpp"
void NS::Foo::f()
{ /*..*/ }
void NS::Foo::g()
{ /*..*/ }
为了使用名字空间成员,必须使用成员的全路径名,它由名字空间后跟::合成原名组成。因此,类Foo的全路径名是NS::Foo。这样编译器便可以知道NS是一个名字空间名,头文件Foo.hpp必须在引用NS之前被包含。
名字空间是可以扩展的。也就是说可以声明类,而且所声明的类在其它的.cpp文件中是相同的名字空间成员:
//Bar.hpp
namespace NS //扩展 NS
{
class Bar
{
public:
void a();
void b();
};
}
在Bar.cpp文件中:
#include "Bar.hpp"
void NS::Bar::a()
{/*..*/}
void NS::Bar::b()
{/*..*/}
可以看出,虽然Foo和Bar这两个类在不同的头文件中声明,但它们都是名字空间NS的成员。并且编译器和链接器将这两个类看成是同一名字空间的成员。那么,如何在应用程序中使用这些类呢?
在文件main.cpp中,必须要包含声明类Foo和Bar的头文件并加上相应的名字空间引用声明-using:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using NS::Bar; //使用名字空间
using NS::Foo; //同上
Bar b;
Foo f;
f.f();
//...
}