C++ 编译器如何知道要调用哪个虚函数实现?
这是一个来自 http://www.cplusplus.com/doc 的多态性示例/tutorial/polymorphism.html(为便于阅读而编辑):
Here is an example of polymorphism from http://www.cplusplus.com/doc/tutorial/polymorphism.html (edited for readability):
// abstract base class
#include <iostream>
using namespace std;
class Polygon {
protected:
int width;
int height;
public:
void set_values(int a, int b) { width = a; height = b; }
virtual int area(void) =0;
};
class Rectangle: public Polygon {
public:
int area(void) { return width * height; }
};
class Triangle: public Polygon {
public:
int area(void) { return width * height / 2; }
};
int main () {
Rectangle rect;
Triangle trgl;
Polygon * ppoly1 = ▭
Polygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << endl; // outputs 20
cout << ppoly2->area() << endl; // outputs 10
return 0;
}
我的问题是编译器如何知道 ppoly1 是一个 Rectangle 而 ppoly2 是一个三角形,以便它可以调用正确的 area() 函数?它可以通过查看Polygon * ppoly1 = ▭"来发现这一点line 并且知道 rect 是一个 Rectangle,但这并不适用于所有情况,不是吗?如果你做了这样的事情怎么办?
My question is how does the compiler know that ppoly1 is a Rectangle and that ppoly2 is a Triangle, so that it can call the correct area() function? It could find that out by looking at the "Polygon * ppoly1 = ▭" line and knowing that rect is a Rectangle, but that wouldn't work in all cases, would it? What if you did something like this?
cout << ((Polygon *)0x12345678)->area() << endl;
假设您被允许访问该随机内存区域.
Assuming that you're allowed to access that random area of memory.
我会对此进行测试,但我目前无法在我使用的计算机上进行测试.
I would test this out but I can't on the computer I'm on at the moment.
(我希望我没有遗漏一些明显的东西......)
(I hope I'm not missing something obvious...)
推荐答案
每个对象(属于具有至少一个虚函数的类)都有一个指针,称为 vptr
.它指向其实际类的 vtbl
(每个具有虚函数的类至少有一个;对于某些多重继承场景可能不止一个).
Each object (that belongs to a class with at least one virtual function) has a pointer, called a vptr
. It points to the vtbl
of its actual class (which each class with virtual functions has at least one of; possibly more than one for some multiple-inheritance scenarios).
vtbl
包含一堆指针,每个指针对应一个虚函数.所以在运行时,代码只是使用对象的 vptr
来定位 vtbl
,并从那里找到实际重写函数的地址.
The vtbl
contains a bunch of pointers, one for each virtual function. So at runtime, the code just uses the object's vptr
to locate the vtbl
, and from there the address of the actual overridden function.
在您的特定情况下,Polygon
、Rectangle
和 Triangle
每个都有一个 vtbl
,每个都有一个指向其相关 area
方法的入口.您的 ppoly1
将有一个 vptr
指向 Rectangle
的 vtbl
和 ppoly2
与 Triangle
的 vtbl
类似.希望这会有所帮助!
In your specific case, Polygon
, Rectangle
, and Triangle
each has a vtbl
, each with one entry pointing to its relevant area
method. Your ppoly1
will have a vptr
pointing to Rectangle
's vtbl
, and ppoly2
similarly with Triangle
's vtbl
. Hope this helps!
相关文章