扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
在本页阅读全文(共19页)
莎士比亚有一个关于名字的说法。“What’s in a name?”他问道,“A rose by any other name would smell as sweet.”(语出《罗密欧与朱丽叶》第二幕第二场,朱生豪先生译为:“姓名本来是没有意义的;我们叫做玫瑰的这一种花,要是换了个名字,他的香味还是同样的芬芳。”梁实秋先生译为:“姓算什么?我们所谓有玫瑰,换个名字,还是一样的香。”——译者注)。莎翁也写过“he that filches from me my good name ... makes me poor indeed.”(语出《奥塞罗》第三幕第三场,朱生豪先生译为:“可是谁偷去了我的名誉,那么他虽然并不因此而富足,我却因为失去它而成为赤贫了。”梁实秋先生译为:“但是他若夺去我的名誉,于他不见有利,对我却是一件损失哩。”——译者注)。好吧!在C++中,我们该用哪种态度对待通过继承得到的名字呢?
事情的实质与继承没什么关系。它与作用域有关。我们都知道它在代码中是这样的,
|
读入x的语句指涉local变量x,而不是global变量x,因为内层作用域的名字覆盖(“遮蔽”)外层作用域的名字。我们可以像这样形象地表示作用域的状况:
当编译器在someFunc的作用域中遇到名字x时,他们巡视local作用域看看是否有什么东西叫这个名字。因为那里有,它们就不再检查其它作用域。在此例中,someFunc的x类型为double,而global x类型为int,但这不要紧。C++的name-hiding规则仅仅是覆盖那个名字。而相对应的名字的类型是否相同是无关紧要的。在此例中,一个名为x的double覆盖了一个名为x的int。
加入inheritance以后。我们知道当我们在一个derived class member function内指涉位于base class内的一件东西(例如,一个member function,一个typedef,或者一个data member)时,编译器能够找到我们指涉的东西是因为derived classes继承到声明于base classes中的东西。实际中的运作方法是将derived class的作用域嵌套在base class作用域之中。例如:
|
本例中包含的既有public名字也有private名字,既有data members也有member functions。member functions既有pure virtual的,也有simple (impure) virtual的,还有non-virtual的。那是为了强调我们谈论的事情是关于名字的。例子中还可以包括其它类型的名字,例如,enums,nested classes,和typedefs。在这里的讨论中唯一重要的事情是“它们是名字”。与它们是什么东西的名字毫不相关。这个示例中使用了single inheritance,但是一旦你理解了在single inheritance下会发生什么,C++在multiple inheritance下的行为就很容易预见了。
假设mf4在derived class中被实现,其中一部分,如下:
|
当编译器看到这里对名字mf2的使用,它就必须断定它指涉什么。它通过搜索名为mf2的某物的定义的作用域来做这件事。首先它在local作用域中搜索(也就是mf4的作用域),但是它没有找到被称为mf2的任何东西的声明。然后它搜索它的包含作用域,也就是class Derived的作用域。它依然没有找到叫做mf2的任何东西,所以它上移到它的上一层包含作用域,也就是base class的作用域。在那里它找到了名为mf2的东西,所以搜索停止。如果在Base中没有mf2,搜索还会继续,首先是包含Base的namespace(s)(如果有的话),最后是global作用域。
我刚刚描述的过程虽然是正确的,但它还不是一个关于C++中名字如何被找到的完整的描述。无论如何,我们的目的不是为了充分了解关于写一个编译器时的名字搜索问题。而是为了充分了解如何避免令人吃惊的意外,而对于这个任务,我们已经有了大量的信息。
再次考虑前面的示例,而且这一次我们overload mf1和mf3,并且为Derived增加一个mf3的版本。(Derived对mf3——一个通过继承得到的non-virtual function——的重载,使得这个设计立即变得可疑,但是出于对inheritance之下名字可见性问题的关心,我们就装作没看见。)
|
以上代码导致的行为会使每一个第一次遇到它的C++程序员吃惊。基于作用域的名字覆盖规则(scope-based name hiding rule)不会有什么变化,所以base class中的所有名为mf1和mf3的函数被derived class中的名为mf1和mf3的函数覆盖。从名字搜索的观点看,Base::mf1和Base::mf3不再被Derived继承!
|
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者