Vai*_*pai 21 c++ java virtual-functions
在C++中,我必须明确指定'virtual'关键字以使成员函数'overridable',因为当成员函数被覆盖时,会产生创建虚拟表和vpointer的开销(因此每个成员函数都隐式不能覆盖表现原因).
当子类提供具有相同名称和签名的单独实现时,它还允许隐藏成员函数(如果未覆盖).
在C#中也使用相同的技术.我想知道为什么Java摆脱了这种行为,并默认使每个方法都可以覆盖,并提供了在显式使用'final'关键字时禁用覆盖行为的能力.
Jam*_*mes 27
更好的问题可能是"为什么C#有非虚方法?" 或者至少,为什么默认情况下它们不是虚拟的,可以选择将它们标记为非虚拟?
在C++中,有一个想法(正如Brian所指出的那样),如果你不想要它,你就不用付钱了.问题在于,如果你真的想要它,这通常意味着你最终会为此付出代价.在大多数Java实现中,它们是为大量虚拟调用而明确设计的; vtable实现往往比非虚拟调用快,几乎不贵,这意味着非虚函数的主要优点就会丢失.此外,JIT编译器可以在运行时内联虚拟函数.因此,出于效率的考虑,很少有原因其实要使用非虚函数.
因此,它很大程度上归结为最不惊讶的原则.它告诉我们所有方法都以相同的方式运行,其中一半是虚拟的,一半是非虚拟的.由于我们需要至少有一些虚拟方法来实现这种多态性,所以将它们都设置为虚拟是有意义的.此外,有两种具有相同签名的方法只是要求自己在脚下射击.
多态性也决定了对象本身应该控制它的作用.它的行为不应该决定客户端是认为它是FooParent还是FooChild.
编辑:所以我被称为我的断言.下一段是我的猜想,而不是事实陈述.
所有这些有趣的副作用是Java程序员倾向于非常大量地使用接口.由于虚方法优化使得接口的成本基本上不存在,它们允许您使用List(例如)而不是ArrayList,并在稍后的某个日期通过简单的单行更改将其切换为LinkedList.没有额外的罚款.
编辑:我还会提供一些消息来源.虽然不是原始资源,但他们确实来自Sun,解释了HotSpot的一些工作原理.
Nei*_*fey 11
所以Java的基本原理可能是这样的:面向对象语言的全部意义在于可以扩展事物.因此,就纯粹的设计而言,将可扩展性视为"特殊情况"确实没有意义.
请记住,Java可以在运行时进行编译.因此,C++编译中的一些性能参数就会消失.在C++中,如果某个类可能被覆盖,那么编译器必须采取额外的步骤.在Java中,没有任何关于它的谜团:在任何给定的时刻,JVM都知道某个特定的方法/类是否被覆盖,而这基本上是重要的.
请注意,final关键字主要是关于程序设计,而不是优化.JVM不需要此信息来查看是否已覆盖类/方法!
| 归档时间: |
|
| 查看次数: |
3110 次 |
| 最近记录: |