条款33:避免遮掩继承而来的名称
Avoid hiding inherited names.
内容:
相信大家对变量作用域的"名称遮掩"现象已经很熟悉了,比如下面这段代码: 这时当编译器处于someFunc的作用域内并遭遇到名称x时,它先在本作用域中查找具有x名称的变量,如果找不到再到其他作用域找.但这里的两个作用域中的具有相同名称x的变量具有不同的数据类型(someFun中的为double而global中的为int),这不是需要在意的问题.C++的名称遮掩规则只关注名称的遮掩,而名称是否具有相同的类型并不重要.下面我们来重点看一下类中的名称遮掩问题.
就像独立的普通函数一样,类中的函数也具有作用域的问题,先看下面这段代码: 这段代码所构造的类作用域大体上可以用下面图示表示:
当编译器执行在mf4中遇到mf2名称时候,开始在本作用域内(Derived作用域)寻找名称匹配,未果,开始在
上一层作用域中(Base作用域中)查找,哦也,找到了,调用这个版本的mf2(Base::mf2).如果它没有找到,则它
开始在可能的namespace中查找,还是没找到的话就到global区域中查找.
现在我们在类中添加一下重载函数,看"名称遮掩"会怎么发生,新代码如下: 这时候作用域的大概图示可以描述如下:
我们现在写一段测试代码去test! 这种结果是不是很出乎你的意料,shit! base class内的mf1和mf3的函数都被derived class内的相应
的名字函数遮掩掉了,Base::mf1与Base::mf3竟然不再被子类继承,偶滴神啊,这种愚蠢的事情怎么能发生,
快快阻止它吧!这问题不大,我们可以用using声明式达成目标,我们再来看代码: 重新test上面那段代码: 喔也,一切ok!这意味着如果你继承base class并加上重载函数,而你又希望重新定义或覆写其中一部分,
那么你必须为那些原本被遮掩的每个名称引入一个using声明式,否则某些你希望继承的名称会被遮掩.
而有的时候你不想继承base classes的所有函数.在public继承中这显然不能发生,这违反了"base与
derived classes之间的is-a关系.",然而在private继承下这是可能(条款39我们会详述).子类可以用
using声明式来引用Base的函数. 好了,今天的topic就over了!
请记住:
◆ derived class内的名称会遮掩base classes内的名称.在public继承下没有人希望如此.
◆ 为了让遮掩的名称再见天日,可使用using声明式或转交函数(forwarding functions).