为什么有些语言更喜欢静态方法绑定而不是动态方法绑定?
为什么 C++、C# 和 Ada 95 中默认决定使用静态方法绑定,而不是动态方法绑定。
实现速度的提升值得抽象和可重用性的损失吗?
Why is the default decision in C++, C#, and Ada 95 to use static method binding, rather than dynamic method binding.?
Is the gain in implementation speed worth the loss in abstraction and re-usability?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一般来说,您可以考虑必须设计基类以实现可扩展性。如果成员函数(使用 C++ 词汇)没有被设计为可重写,那么在实践中重写它很可能是不可能的,并且在不了解类设计者的情况下肯定不可能实现认为是实施细节,如有更改,恕不另行通知。
对于两种语言的一些额外注意事项(我不太了解 C#,无法撰写相关内容):
如果选择不同,Ada 95 将会与 Ada 83 存在兼容性问题。考虑到 Ada 95 的整个对象模型,采取不同的做法是没有意义的(但您可以认为兼容性是选择对象模型的一个因素)。
对于 C++ 来说,性能无疑是一个因素。 不用为不使用的东西付费原则以及将 C++ 用作更好的 C 的可能性对其成功起了很大的作用。
In general, you can consider that you have todesign the base class for extensibility. If a member function (to use the C++ vocabulary) isn't designed to be overridden, there is a good chance than overriding it will in practice not be possible and for sure it won't it be possible without knowledge of what the class designer think is implementation details and will change without giving you prior notice.
Some additional considerations for two languages (I don't know C# enough to write about it):
Ada 95 would have had compatibility issues with Ada 83 if the choice was different. And considering the whole object model of Ada 95, doing it differently would have make no sense (but you can consider that compatibility was a factor in the choice of the object model).
For C++, performance was certainly a factor. The you don't pay for what you don't use principle and the possibility to use C++ just as a better C was quite instrumental in its success.
显而易见的答案是因为大多数函数不应该是虚拟的。正如 AProgrammer 指出的那样,除非函数被明确设计为可重写,否则您可能无法在不破坏类不变量的情况下重写它(无论是否是虚拟函数)。 (例如,当我使用 Java 工作时,我最终将大多数函数声明为
final
,这是一个良好的工程问题。C++ 和 Ada 做出了正确的决定:作者必须明确声明该函数是设计的 另外,C++ 和(我认为)Ada 支持值语义,而在 Java 中,值语义不能很好地工作;像
java.lang.String
这样的类是final 的。
,为了然而,对于许多应用程序程序员来说,不必费心,因为它不是默认的(以类似的方式,太多的 C++ 程序员在类是多态时省略了禁止复制和赋值。) ,即使一个类是多态的,并且是为继承而设计的,契约仍然是在基类中指定的,并且在合理的范围内强制执行,通常,这意味着
public
。函数不是虚函数,因为定义和执行合同的是公共职能。The obvious answer is because most functions shouldn't be virtual. As AProgrammer points out, unless a function has been designed explicitly to be overridden, you probably can't override it (virtual or not) without breaking class invariants. (When I work in Java, for example, I end up declaring most functions
final
, as a matter of good engineering. C++ and Ada make the right decision: the author must explicitly state that the function is designed to be overridden.Also, C++ and (I think) Ada support value semantics. And value semantics doesn't work well with polymorphism; in Java, classes like
java.lang.String
arefinal
, in order to simulate value semantics for them. Far to many applications programmers, however, don't bother, since it's not the default. (In a similar manner, far too many C++ programmers omit to inhibit copy and assignment when the class is polymorphic.)Finally, even when a class is polymorphic, and designed for inheritance, the contract is still specified, and in so far as is reasonable, enforced, in the base class. In C++, typically, this means that
public
functions are not virtual, since it is the public functions which define and enforce the contract.我不能谈论 Ada,但对于 C++ 来说,C++ 设计的两个重要目标是:
虽然这些都不一定决定动态绑定不能被选择为默认值,具有静态方法绑定(我假设您的意思是非虚拟成员函数)似乎确实更“适合”这些设计目标。
I can't speak about Ada, but for C++ two important goals for the design of C++ were:
While neither of these would necessarily dictate that dynamic binding couldn't have been chosen to be the default, having static method binding (I assume you mean non-virtual member functions) does seem to 'fit' better with these design goals.
我将给出迈克尔·伯尔答案的另外三分之二之一。
对于 Ada 来说,一个重要的设计目标是该语言适合系统编程并在小型实时嵌入式设备(例如:导弹和炸弹 CPU)上使用。也许现在有一些技术可以让动态语言很好地完成这些事情,但在 70 年代末和 80 年代初首次设计该语言时,肯定还没有这种技术。 Ada95 当然不能从根本上偏离原始语言的基本底层设计,就像 C++ 不能偏离 C
一样。话虽这么说,Ada 和 C++(当然还有 C#?)都提供了一种进行动态方法绑定的方法(“动态”)派遣”)如果你真的想要的话。在这两种情况下,它都是通过指针访问的,恕我直言,这很容易出错。它还会让调试变得有点痛苦,因为很难仅从源头准确判断正在调用什么。所以除非我真的需要它,否则我会避免它。
I'll give one of the other two thirds of Michael Burr's answer.
For Ada it was an important design goal that the language be suitable for system's programming and use on small realtime embedded devices (eg: missile and bomb CPUs). Perhaps there are now techniques that would allow dynamic languages to do such things well, but there certianly weren't back in the late 70's and early 80's when the language was first being designed. Ada95 of course could not radically deviate from the orginal language's basic underlying design, any more than C++ could from C.
That being said, both Ada and C++ (and certianly C# as well?) provide a way to do dynamic method binding ("dynamic dispatch") if you really want it. In both it is accesed via pointers, which IMHO are kind of error-prone. It can also make things a bit of a pain to debug, as it is tough to tell from sources alone exactly what is getting called. So I avoid it unless I really need it.