C++基础(9.3)——名称空间(namespace)

名称空间(namespace)

  • 声明区域(declaration region)
    声明区域是可以在其中进行声明的区域。例如,可以在函数外面声明全局变量,对于这种变量,其声明区域为其声明所在的文件。对于在函数中声明的变量,其声明区域为其声明所在的代码块。
  • 潜在作用域(potential scope)
    变量的潜在作用域从声明点开始,到其声明区域的结尾。因此潜在作用域比声明区域小,这是由于变量必须定义后才能使用。
    + 名称空间特性
/* Ok 1. 名称空间可以是全局的 */
namespace Jack {
    
    
	double pail;
	void fetch();
	int pal;
}

/* Ok */
namespace Jill {
    
    
	double bucket(double n) {
    
    ...}
	double fetch;
	int pail;
}

/* 2. 名称空间是开放的(open),可以把名称加入到已有的名称空间中 */
namespace Jack {
    
    
	int b;
}

/* 3. 名称空间可以在另一个名称空间中 */
namespace A {
    
    
	namespace B {
    
    
		int a;
		int b;
	}
}
int main()
{
    
    
	/* 4. 名称空间不可以位于代码块中,默认情况下,
		在名称空间中声明的名称的链接性为外部的(除非它引用了常量) */
	// namespace hello {} No
	
	/* use namespace */
	// 通过作用域解析运算符::,使用名称空间来限定该名称
	Jack::Pail = 12.34;
	/* 未被修饰的名称(如pail)称为未限定的名称(unqualified name); 包含名称空间的名称(如Jack::pail)限定的名称 */
}
  • using声明与using编译指令
    C++提供了using声明和using编译指令简化对名称空间中名称的使用,using声明使特定的标示符可用,using编译使整个名称空间可用
/* using 声明 */
using Jack::pail; // a using declaration

/* using编译指令与using声明比较 */
int main() 
{
    
    
	/* using声明 */
	double pail;
	using Jack::pail; // not allow,当某个名称已经在函数中存在,不可以使用using声明导入相同的名称

	/* 2. using编译指令 */
	/* 使用using编译指令导入一个名称空间与使用using声明是不同的,更像是使用大量的作用域解析运算符,*/
	using namespace Jack; // ok 但是相同的局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样
	pail = 3;
	cout << Jack::pail << endl;  // 0
	return 0;
}
  • 名称空间的其他特性
/* 1. 可以将名称空间声明进行嵌套 */
namespace elements {
    
    
	namespace fire {
    
    
	};
}

/* 2. 可以在名称空间中使用using编译指令和using声明 */
namespace myth {
    
    
	using Jack::pail;
	using namespace elements;
}

/* 3. 可以给名称空间创建别名来简化对嵌套空间的声明 */
//namespace myth = myt;
namespace MEF = myth::elements::fire;
//using MEF::flame;

/* 4. 未命名的名称空间 */
/* 未命名名称空间中声明的名称的潜在作用域为:从声明点到该声明末尾,这个方面与全局变量相似
由于没有名称,所以不能显式的使用using编译指令或using声明来使其在其他位置可用。不可以在其
所属文件之外使用,这提供了链接性为内部的静态变量的替代品(对于没有声明为static的符号具有外部链接性,所以它们的名字在整个程序中必须唯一。典型的C解决方法为将这些符号声明为static,使它们的链接性由外部变为内部)
*/
// 例如:
static int counts; // static storage, internal linkage
int other();
int func(){
    
     ... }
int other(){
    
     ... }
// 采用名称空间的方法
namespace {
    
    
	int counts; // static storage, internal linkage
}
int func();
int other();

int main()
{
    
    
	/* 如果要访问jill::fetch */
	cin >> myth::fetch;
	/* 若没有与之冲突的变量 */
	using namespace myth;
	cin >> fetch;

	using MEF::flame;
	return 0;
}
  • 名称空间指导原则
    1. 使用在已命名的名称空间中声明的变量,而不是使用外部全局变量
    2. 使用在未命名的名称空间中声明的变量,而不是静态全局变量
    3. 如果开发一个函数库或类库,将其放在一个名称空间中。C++提倡将标准函数库放在名称空间std中,扩展来自C语言的函数。但并非所有的编译器都完成了这种过度
    4. 仅将编译指令using作为一种将旧代码转换为使用名称空间的权宜之计
    5. 不要在头文件中使用using编译指令。首先,这样做掩盖了要让那些名称可用;另外包含头文件的顺序可能影响程序的行为。如果非要使用using编译指令using,应该将其放在#include之后
    6. 导入名称时,首选使用作用域解析运算符或using声明的方法
    7. 对于using声明,首选将其作用域设置为局部而不是全局。

猜你喜欢

转载自blog.csdn.net/gripex/article/details/105216668