为什么没有多边形没有指针/引用? [英] Why doesn't polymorphism work without pointers/references?

查看:129
本文介绍了为什么没有多边形没有指针/引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在SO上找到了类似标题的一些问题,但是当我阅读答案时,他们集中在问题的不同部分,这是真正具体的(例如STL /容器)。



有人可以告诉我为什么你必须使用指针/引用来实现多态性?我可以理解指针可以帮助 - 但肯定引用只区分传递值和传递引用之间



当然,只要你分配内存在因此,你可以有动态绑定,然后这已经足够 - 显然不是。

解决方案

具有在编译时已知的固定类型和大小(如果它可以并且确实具有其地址)在其生存期期间总是存在于固定地址。这些是继承自C的特性,有助于使这两种语言适合于低级系统编程。 (所有这一切都遵循as-if规则,虽然:一个合格的编译器可以自由地做任何它喜欢的代码,只要它可以证明对任何行为的合格程序没有可检测的效果是有保证的)



定义C ++中的一个函数(或多或少,不需要极端语言律师)作为基于对象的运行时类型执行;当直接调用对象时,这将始终是对象的编译时类型,因此当以这种方式调用 virtual 函数时,没有多态性。

请注意,这不一定是这种情况: virtual 函数的对象类型通常在C ++中用每个 - 指向每个类型唯一的 virtual 函数的表的对象指针。如果这样倾向,一个C ++的一些假设变体的编译器可以实现对象上的赋值(例如 Base b; b = Derived())复制对象的内容和 virtual 表指针,如果 Base 派生的大小相同。在两者不是相同大小的情况下,编译器甚至可以插入将程序暂停任意时间量的代码,以便重新排列程序中的存储器,并以可能的方式更新对该存储器的所有可能的引用被证明对程序的语义没有可检测的影响,如果没有找到这样的重排,则终止该程序:虽然这将是非常低效的,并且不能保证永远停止,对于赋值运算符显然不期望的特征有



因此,通过允许引用和指向对象的引用和指向其声明的编译时类型的对象来实现C ++中的多态性,其任何亚型。当通过引用或指针调用 virtual 函数时,编译器无法证明引用或指向的对象是具有特定已知实现的运行时类型 virtual 函数,编译器插入查找正确的 virtual 函数来调用运行时的代码。它不一定是这样,引用和指针可以被定义为非多态性(不允许它们引用或指向它们的声明类型的子类型),并迫使程序员想出实现多态性的替代方法。后者显然是可能的,因为它一直在C中完成,但在那一点,没有太多理由有一个新的语言。



总之,语义的C ++被设计为允许面向对象的多态性的高级抽象和封装,同时仍然保留特征(例如低级访问和存储器的明确管理),这允许它适合于低级开发。你可以很容易地设计一种具有其他语义的语言,但它不会是C ++,并且会有不同的好处和缺点。


I did find some questions already on SO with similar title- but when I read the answers they were focussing on different parts of the question which were really specific (e.g. STL/containers).

Could someone please show me why you must use pointers/references for implementing polymorphism? I can understand pointers may help- but surely references only differentiate between pass-by-value and pass-by-reference??

Surely so long as you allocate memory on the heap- so that you can have dynamic binding then this would have been enough- obviously not.

解决方案

In C++, an object always has a fixed type and size known at compile-time and (if it can and does have its address taken) always exists at a fixed address for the duration of its lifetime. These are features inherited from C which help make both languages suitable for low-level systems programming. (All of this is subject to the as-if, rule, though: a conforming compiler is free to do whatever it pleases with code as long as it can be proven to have no detectable effect on any behavior of a conforming program that is guaranteed by the standard.)

A virtual function in C++ is defined (more or less, no need for extreme language lawyering) as executing based on the run-time type of an object; when called directly on an object this will always be the compile-time type of the object, so there is no polymorphism when a virtual function is called this way.

Note that this didn't necessarily have to be the case: object types with virtual functions are usually implemented in C++ with a per-object pointer to a table of virtual functions which is unique to each type. If so inclined, a compiler for some hypothetical variant of C++ could implement assignment on objects (such as Base b; b = Derived()) as copying both the contents of the object and the virtual table pointer along with it, which would easily work if both Base and Derived were the same size. In the case that the two were not the same size, the compiler could even insert code that pauses the program for an arbitrary amount of time in order to rearrange memory in the program and update all possible references to that memory in a way that could be proven to have no detectable effect on the semantics of the program, terminating the program if no such rearrangement could be found: this would be very inefficient, though, and could not be guaranteed to ever halt, obviously not desirable features for an assignment operator to have.

So in lieu of the above, polymorphism in C++ is accomplished by allowing references and pointers to objects to reference and point to objects of their declared compile-time types and any subtypes thereof. When a virtual function is called through a reference or pointer, and the compiler cannot prove that the object referenced or pointed to is of a run-time type with a specific known implementation of that virtual function, the compiler inserts code which looks up the correct virtual function to call a run-time. It did not have to be this way, either: references and pointers could have been defined as being non-polymorphic (disallowing them to reference or point to subtypes of their declared types) and forcing the programmer to come up with alternative ways of implementing polymorphism. The latter is clearly possible since it's done all the time in C, but at that point there's not much reason to have a new language at all.

In sum, the semantics of C++ are designed in such a way to allow the high-level abstraction and encapsulation of object-oriented polymorphism while still retaining features (like low-level access and explicit management of memory) which allow it to be suitable for low-level development. You could easily design a language that had some other semantics, but it would not be C++ and would have different benefits and drawbacks.

这篇关于为什么没有多边形没有指针/引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆