日常啃书系列----名称空间总结

本文深入探讨C++中名称空间的引入原因、使用方式及特性,包括声明区域、作用域、潜在作用域的概念,using声明与编译指令的区别,以及名称空间的嵌套和别名创建。
唉,啃书后想着该写点什么(才不会承认是记性实在堪忧不得不写……)
本篇没有长篇代码(真好……)
引入名称空间的意义:

最简单的说,如我们所知,当随着项目的增大,名称相互冲突的可能性必然会增加,特别是使用多个厂商的类库时,比如A库和B库都定义了 NODE类,但定义的方式不兼容,用户可能想用A库而不想用B库的NODE类,那么问题来了,怎么区分它们呢?

当当当当~ 名称空间的概念就被C++引入啦!

一 . 相关概念:

在具体说之前让我们先弄明白一些名称含义方便后文描述~
1.声明区域and 作用域and 潜在作用域

说什么都不如一张图好使,直接上图!

在这里插入图片描述

潜在作用域:

从声明点开始,到其声明区域的结尾

作用域:

即变量对于程序而言可见的范围(因为变量在其潜在作用域中可能会被另一个嵌套声明的同名变量隐藏,或者说默认被覆盖,但依然可以强制使用)

声明区域:

可以在其中进行声明的区域(废话)如第一个全局声明的num的声明区域是该文件,第二个num的声明区域是main函数……

图中的颜色区域显示了每个被声明的num的潜在作用域,作用域是未被比其作用优先级高的num覆盖的部分(优先级为:黄 色< 绿色 <红色)

2. using声明 和 using编译指令
using声明:
      使特定标识符在整个作用域内可用
using编译指令:
      使整个名称空间的所有标识符在整个作用域内可用
好啦,大概一些重要的概念先摆这,接下来看这些概念在代码中的具体体现吧~

二 . 使用方式:(以我们熟悉的 std 为例)

1.作用域解析运算符 ::
                 std::cin >> a;   
                 std::cout <<  a;
                 std::cin >> a;
                 上面反映了该种方法的作用范围,仅该次使用有效               
2. using声明
    void su(){
             int a;
             using std::cin >> a;
             using std::cout << a;
             cin >> a;
             cout << a;       
    }
    void ge(){
        int a;
        cin >> a;   // false,超出其作用域
 }
3.using编译指令: 配合关键字 namespace 使用
         void su(){
             using namespace std; 
             int a;
             cin >> a;
             cout << a;       
    }
    void ge(){
        int a;
        cin >> a;   // false,超出其作用域
 }  
啊~ 应该说清楚了吧……下面来看一看名称空间有哪些特性

三 . 特性 :

1.放置位置:
   可以是全局,也可以位于另一个名称空间中,但是!!! 不能位于代码块中!!

全局:

namespace Wang{
int age;
std::string name;
void fetch();
struct person{…};
}

int main(){
…………
}

嵌套 :

namespace Yang{

namespace Li{
……
int age;
void fetch(string a){……}
……
}
……
}

2.使用及其范围:
(此处为补充,主要是using声明与编译指令的区别,说得多不如直接上代码吧)
 namespace Yang{
 	
 	  namespace Li{
 	   	  …… 
 	  	   int age;
 	  	  …… 
	   }
	   
	   …… 
 }
 
namespace Wang{
	int age;
  using	std::string name;  //using声明和using编译指令在名称空间中也可以使用 
	void fetch(string a){……}
	struct person{};
}

namespace xiao{
	int age;
}

using namespace Yang::Li; // 内部名称也可用 
   char age;
 int main(){
 	
/* using 声明 */
 	 // using xiao::age;//编译器不允许同时使用,会产生二义性 
	  using Wang::age;
	 // int age;  //false
	  cin >> age; //Wang::age
	  cin >> ::age; // global    age
//////////////////////////////////////////////////////////////////	  
	   using Wang::fetch; //此处后面说%
	  fetch("sdg");  
////////////////////////////////////////////////////////////////	  
/*using 编译指令 */	 
      
      using namespace Wang;
        int age; //right,将覆盖 Wang::age 
        cin >> age; // 为main中定义的age 
        cin >> Wang::age; 
        cin >> ::age;
	  
 } 
3.创建别名:
    namespace Mfg = Wang;  //Mfg此处才声明,Wang已经声明,此后Mfg与Wang等效
4.未命名的名称空间:
作用和内部静态变量差不多,因为若是全局声明,其潜在作用域为从声明点到该声明区域末尾,从这个方面看和全局变量类似,又由于没有名字,外部无法进行调用,这又与static关键字声明的全局变量类似

so下面两个等价

  static int a;


  namespace{
       int a;
   }

四. 杂谈:

1.想必有人注意到前面的 using Wang::fetch 只使用了名称(没有问题!),并没有描述该函数的返回值类型或函数特征,因此,如果该函数被重载,则该using 声明将会导入所有的版本
2.不要在头文件中使用using编译指令,这样做首先会掩盖了要让哪些名称可用,此外包含头文件的顺序可能影响程序的行为,如果你头铁非要使用using编译命令,麻烦尽量将其放在所有预处理器编译指令#include之后 !!!
2.导入名称时,优选作用域解析运算符或using声明,名称空间的开放性意味着名称空间的名称可能分散在多个地方,反正using的两种使用与使用作用域解析运算符相比都会增加名称冲突的可能性,但是……方便啊!

同志们!喜欢就动动小手点个赞啊!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值