引子
为引出本文主题,先举个例子,以便后文对照理解:某学校一年招了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命名变量:))。而不同函数或模块间的命名又互不干扰,因此局部域没有命名冲突问题。