为什么没有指针/引用就不能工作多态?
我确实在 SO 上发现了一些标题相似的问题――但是当我阅读答案时,他们关注的是问题的不同部分,这些部分非常具体(例如 STL/容器)..
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.
推荐答案
在 C++ 中,对象始终具有在编译时已知的固定类型和大小,并且(如果可以并且确实获取了地址)始终存在于在其生命周期内固定地址.这些是从 C 继承的特性,有助于使这两种语言都适用于低级系统编程.(不过,所有这些都受制于 as-if, 规则:只要可以证明它对保证的符合标准的程序的任何行为没有可检测的影响,符合标准的编译器就可以自由地对代码做任何事情.按标准.)
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.)
C++ 中的 virtual
函数被定义为(或多或少地,不需要极端的语言律师)基于对象的运行时类型执行;当直接在对象上调用时,它将始终是对象的编译时类型,因此以这种方式调用 virtual
函数时没有多态性.
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.
请注意,不一定非要如此:具有 virtual
函数的对象类型通常在 C++ 中实现,每个对象都有一个指向 virtual
每种类型独有的功能.如果愿意,C++ 的一些假设变体的编译器可以实现对对象的赋值(例如 Base b; b = Derived()
)作为复制对象的内容和 virtual
表指针以及它,如果 Base
和 Derived
的大小相同,这将很容易工作.在两者大小不同的情况下,编译器甚至可以插入暂停程序任意时间的代码,以便重新排列程序中的内存并以可能的方式更新对该内存的所有可能引用证明对程序的语义没有可检测到的影响,如果找不到这样的重新排列,则终止程序:但是,这将非常低效,并且不能保证永远停止,显然不是赋值运算符想要的特性有.
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.
因此,代替上述内容,C++ 中的多态性是通过允许对对象的引用和指针来引用和指向其声明的编译时类型及其任何子类型的对象来实现的.当通过引用或指针调用 virtual
函数时,编译器无法证明所引用或指向的对象是具有该 virtual<的特定已知实现的运行时类型/code> 函数,编译器插入代码来查找正确的
virtual
函数来调用运行时.它也不必是这样:引用和指针可以被定义为非多态的(不允许它们引用或指向其声明类型的子类型)并迫使程序员想出实现多态的替代方法.后者显然是可能的,因为它一直都是用 C 语言完成的,但在这一点上,根本没有太多理由拥有一门新语言.
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.
总之,C++ 的语义被设计成允许面向对象多态性的高级抽象和封装,同时仍然保留允许它的特性(如低级访问和显式内存管理)适合低级开发.您可以轻松设计一种具有其他语义的语言,但它不会是 C++,并且会有不同的优点和缺点.
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.
相关文章