C++基础补遗篇之作用域和自定义命名空间

引子

为引出本文主题,先举个例子,以便后文对照理解:某学校一年招了3个叫李明的学生,为便于区分:1)按年龄排序分别称大、中、小李明;2)把他们分到不同班,这样各班内部就没有同名的李明,而学校范围内可用1班/2班李明区分;3)大李明加入绘画协会,中李明加入书法协会,小李明加入绘画和外语协会,于是绘画协会里还要用大小或班级区分两个李明。

基本几点:

1.谈到重名,需要指定具体集合范围。全校集里3个李明,各班内部无重名,绘画协会里2个李明。学术化表述就是(校/协会)域内存在命名冲突。

2.方法一:把存在重名元素的集合分成若干子集,同名元素分到不同子集,用子集名+元素名方式区分(123班李明)。

3.方法二:利用重名元素其他固有属性,即名字+属性进行区分(大中小李明)。两种方法可同时使用。

作用域及域内/域间重名

C/C++中变量、函数及类等元素起作用的范围,,称为作用域。在某作用域内为元素命名时,可选择的命名范围称为命名空间(C++新增的一个feature:用户自定义命名空间,也常被简称为命名空间namespace,为区别下文称前者为generalized namespace(GNS).后者user defined namespace(UDNS)。举例:

int c; //①

fun1()

{

int a,b ;

int c; //②

c=a+b; //③

}

fun2()

{

int a, b;

c=a+b; //④

}

int a,b;定义于两个函数内局部作用域,这两个局部作用域的GNS相互独立不干扰,即同层次不同作用域间GNS无重叠,因此两套a,b不冲突,这很好理解。

①处的c作用于全局域,和②处fun1内的c属于不同层的域间同名,这种情况的选择原则是向上就近优先,即:fun1域内③处引用的c就近选择同一域内②定义的局部变量c而不是全局域①的全局变量c;而fun2内没有定义c,④处才向上选择全局域①。

C语言大致分3层作用域:全局、单个文件及局部(函数及更小的{}功能模块内,如for{}, while{}或独立{}),C++开始引入类作用域,后来又加入用户自定义的命名空间作用域(后半部分讲解)。处于不同层次作用域内部和域间的元素,命名冲突及覆盖关系如下:

1)函数或{}模块内的变量(即局部变量)数量有限,命名选择充裕(除非某些懒人总用单个字母a,b,c,d命名变量:))。而不同函数或模块间的命名又互不干扰,因此局部域没有命名冲突问题。

2)C++的类域情况相似,只不过处于同一类域中同名不同参的成员函数还可通过重载机制区分(重载其实利用大中小李明的方法,即参数加函数名区分)。

3)C文件域内不能有同名函数和变量,C++单个文件域内重名的独立函数同样可重载区分。

4)全局作用域包含程序所有源文件、头文件和库,对每个程序唯一,类和非static的独立函数都作用于全局域。实践中大型软件要先由多人分别实现不同模块,最后组合,模块开发阶段类和函数独立命名,因而随意占用全局域的GNS,组合时不同模块间就可能出现类或函数的同名冲突。

可见作用域和命名冲突密切相关,几点原则:

1)作用域内部不能有同名元素,如:函数内不能有同名局部变量;类内不能有同名成员变量;文件和程序全局内不能有同名类。表面上C++重载函数可支持域内重名,实际它额外利用参数信息,真正的名字变成大中小李明,而不仅是李明,所以还是不同名。

的变量和函数,其作用域突破单个文件扩散到程序全局。因此所谓不同文件中不能有同名全局变量和函数,并非不同文件域的GNS空间会重叠,而是因为这些变量和函数实际都作用于全局域,而单个全局域内自然不能有同名元素。

3)不同层次域中的同名元素不冲突,而是遵循向上就近原则决定引用对象。如前例fun1和fun2中c的选择,更进一步,如下例:

extern int c //①

static int c; //②

class A

{

public:

int c; //③

void fun1();

};

A::fun1()

{

int c; //④

int a,b;

c = a+b; //⑤

}

辽远或偏僻的地方,而会常常想起这一次的旅行,想起那座山,那个城,那些人……

C++基础补遗篇之作用域和自定义命名空间

相关文章:

你感兴趣的文章:

标签云: