C++编程中的命名空间基本知识讲解

2020-01-06 14:22:31王旭

通常情况下,在头文件中声明一个命名空间。如果函数实现位于一个单独的文件中,则限定函数名称,如本示例所示。


//contosoData.h 
#pragma once
namespace ContosoDataServer
{
 void Foo();
 int Bar();

}
contosodata.cpp 中的函数实现应使用完全限定名,即使将一个 using 指令放置于文件的顶部也是如此:
#include "contosodata.h"
using namespace ContosoDataServer; 

void ContosoDataServer::Foo()
{
 //no qualification because using directive above
 Bar(); 
}

int ContosoDataServer::Bar(){return 0;}

可以在单个文件中的多个块中声明命名空间,也可在多个文件中声明命名空间。编译器在预处理过程中将各部分联接在一起,产生的命名空间中包含所有部分中声明的所有成员。一个相关示例是在标准库中的每个头文件中声明的 std 命名空间。
指定的命名空间的成员可以在定义的名称的显式限定所声明的命名空间的外部进行定义。但是,定义必须出现在命名空间中的声明位置之后,该命名空间包含在声明的命名空间中。例如:


// defining_namespace_members.cpp
// C2039 expected
namespace V {
  void f();
 }

 void V::f() { }  // ok
 void V::g() { }  // C2039, g() is not yet a member of V

 namespace V {
  void g();
 }
}

当跨多个头文件声明命名空间成员,并且未以正确的顺序包含这些标头时,可能出现此错误。
全局命名空间
如果未在显式命名空间中声明某个标识符,则该标识符属于隐式全局命名空间的一部分。通常情况下,如果可能,尝试避免在全局范围内进行声明,入口点 main 函数除外,它必须位于全局命名空间中。若要显式限定全局标识符,请使用没有名称的范围解析运算符,如 ::SomeFunction(x); 中所示。这将使标识符与任何其他命名空间中具有相同名称的任何内容区分开来,并且还有助于使其他人更轻松地了解你的代码。
Std 命名空间
所有 C++ 标准库类型和函数都在 std 命名空间或嵌套在 std 内的命名空间中进行声明。
嵌套命名空间
可以嵌套命名空间。普通的嵌套命名空间具有对其父级成员的非限定访问权限,而父成员不具有对嵌套命名空间的非限定访问权限(除非它被声明为内联),如下面的示例所示:


namespace ContosoDataServer
{
 void Foo(); 

 namespace Details
 {
  int CountImpl;
  void Ban() { return Foo(); }
 }

 int Bar(){...};
 int Baz(int i) { return Details::CountImpl; } 

}

普通嵌套命名空间可用于封装不属于父命名空间的公共接口的一部分的内部实现详细信息。