- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
翻译 cber
原文出处 .au/~ijoyner/ C++语言的不足之处
译者前言:
要想彻底的掌握一种语言,不但需要知道它的长处有哪些,而且需要知道它的不足之处又有哪些。这样我们才能用好这门语言,避免踏入语言中的一些陷阱,更好地利用这门语言来为我们的工作所服务。
Ian Joyner 的这篇文章以及他所著的《Objects Unencapsulated 》一书中,向我们充分
的展示了 C++的一些不足之处,我们应该充分借鉴于他已经完成的伟大工作,更好的了解C++,从而写出更加安全的 C++代码来。
C++的不足之处讨论系列(一) 虚拟函数
在所有对 C++的批评中,虚拟函数这一部分是最复杂的。这主要是由于 C++中复杂的机制所引起的。虽然本篇文章认为多态(polymorphism)是实现面向对象编程(OOP)的关键特性,但还是请你不要对此观点(即虚拟函数机制是 C++中的一大败笔)感到有什么不安
,继续看下去,如果你仅仅想知道一个大概的话,那么你也可以跳过此节。【译者注: 建议大家还是看看这节会比较好】
在 C++中,当子类改写/重定义(override/redefine)了在父类中定义了的函数时,关键字 virtual 使得该函数具有了多态性,但是 virtual 关键字也并不是必不可少的(只要在父类中被定义一次就行了)。编译器通过产生动态分配(dynamic dispatch)的方式来实现真正的多态函数调用。
这样,在 C++中,问题就产生了:如果设计父类的人员不能预见到子类可能会改写哪个函数,那么子类就不能使得这个函数具有多态性。这对于 C++来说是一个很严重的缺陷,因为它减少了软件组件(software components)的弹性(flexibility),从而使得写出可
重用及可扩展的函数库也变得困难起来。
C++同时也允许函数的重载(overload),在这种情况下,编译器通过传入的参数来进行正确的函数调用。在函数调用时所引用的实参类型必须吻合被重载的函数组(overloade d functions)中某一个函数的形参类型。重载函数与重写函数(具有多态性的函数)的不同之处在于:重载函数的调用是在编译期间就被决定了,而重写函数的调用则是在运行期间被决定的。
当一个父类被设计出来时,程序员只能猜测子类可能会重载/重写哪个函数。子类可以随时重载任何一个函数,但这种机制并不是多态。为了实现多态,设计父类的程序员必须指定一个函数为 virtual,这样会告诉编译器在类的跳转表(class jump table)【译者
窃以为是 vtable,即虚拟函数入口表】中建立一个分发入口。于是,对于决定什么事情是由编译器自动完成,或是由其他语言的编译器自动完成这个重任就放到了程序员的肩上。这些都是从最初的 C++的实现中继承下来的,而和一些特定的编译器及联结器无关。对于重写,我们有着三种不同的选择,分别对应于:千万别,可以及一定要重写
:
1、重写一个函数是被禁止的。子类必须使用已有的函数
2、函数可以被重写。子类可以使用已有的函数,也可以使用自己写的函数,前提是这个函数必须遵循最初的界面定义,而且实现的功能尽可能的少及完善
3、函数是一个抽象的函数。对于该函数没有提供任何的实现,每个子类都必须提供其各自的实现
父类的设计者必须要决定 1 和 3 中的函数,而子类的设计者只需要考虑 2 就行了。对于这些
选择,程序语言必须要提供直接的语法支持。选项 1、
C++并不能禁止在子类中重写一个函数。即使是被声明为 private virtual 的函数也可以被重写。【Sakkinen92】中指出了即使在通过其他方法都不能访问到 private virtual 函数,子类也可以对其进行重写。【译者注:Sakkinen92 我也没看过,但经我简单的测试
,确实可以在子类中重写父类中的 private virtual 函数】
实现这种选择的唯一方法就是不要使用虚拟函数,但是这样的话,函数就等于整个被替换掉了。首先,函数可能会在无意中被子类的函数给替换掉。在同一个 scope 中重新宣告一个函数将会导致名字冲突(name clash);编译器将会就此报告出一个duplicate declaration的语法错误。允许两个拥有同名的实体存在于同一个 scope 中将会导致语义的二义性(ambiguity)及其他问题(可参见于 name overloading 这节)。
下面的例子阐明了第二个问题:
class A
{
public:
void nonvirt(); virtual void virt();
};
class B : public A
{
public:
void nonvirt(); void virt();
};
A a
文档评论(0)