虚函数及多态性是如何实现的
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
虚函数及多态性是如何实现的
一, 引子
话说C++有3个重要特点,多态是其中之一。
所谓多态性,在 upcasting 时,基类类型的指针指向不同的类对象(包括基类本身及其不同的派生类)时,使用该指针可以调用相应对象自己的函数,而不是都调用基类的函数,当然该函数必须为virtual(不需要为 pure virtual)。
代码如下:
可见,虽然都是Instrument 类型,但是对于不同的对象,会很正确地调
用相应的方法。
二, 奇妙的多态是如何实现的
《Thinking in C++》P637
The keyword virtual tells the compiler it should not perform early binding, but late binding.
To accomplish this, the typical compiler creates a single
table(called the VTABLE) for each class that contains virtual functions.
The compiler places the addresses of the virtual functions for that particular class in the VTABLE.
In each class with virtual functions, it secretly places a pointer, called the vpointer (abbreviated as VPTR), which points to the VTABLE for that object.
When you make a virtual function call through a base-class pointer (that is, when you make a polymorphic call), the compiler quietly inserts code to fetch the VPTR and look up the function address in the VTABLE, thus calling the correct function and causing late binding to take place.
There is no explicity type information stored in any of the classes, but there must be sort of type information stored in the objects; otherwise the type could not be established
at runtime. This is true, but the type information is hidden.
There is an example to explain this:
With no virtual functions, the size of the object is exactly what you'd expect: the size of a single int. With a single virtual function in OneVirtual, the size of the object is the size of the NoVirtual plus the size of a void pointer.
It turns out that the compiler inserts a single pointer (the VPTR) into the structure if you have one or more virtual functions. There is no size different between OneVirtual and TwoVirtuals. Thats because the VPTR points to a table of function addresses. You need only one table because all the virtual function addresses are contained in that single table.
本类定义了一个int 数据成员。因为如果没有定义数据成员,对于NoVirtual,编译器为了保证每个该类型的对象有一个不同的地址,会强制其大小为一个非0的值,例如如下声明:
对以上例子稍作修改:
dummy成员),而对于OneVirtual 和TwoVirtuals, 由于隐含了VPTR , 大小本来就不为0,所以没插入dummy成员。