以下是http://www.cplusplus.com/doc/tutorial/polymorphism.html(为便于阅读而编辑)的多态性示例:
// abstract base class #includeusing 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 =▭"行并知道rect是一个Rectangle来找到它,但是在所有情况下都无法工作,不是吗?如果你这样做了怎么办?
cout << ((Polygon *)0x12345678)->area() << endl;
假设您被允许访问该随机内存区域.
我会测试一下,但我现在无法在计算机上测试.
(我希望我不会错过任何明显的东西......)
每个对象(属于具有至少一个虚函数的类)都有一个名为a的指针vptr
.它指向vtbl
其实际类(每个具有虚函数的类至少有一个;对于某些多重继承方案,可能不止一个).
它vtbl
包含一堆指针,每个虚拟函数一个.所以在运行时,代码只是使用对象vptr
来定位vtbl
,并从那里找到实际被覆盖函数的地址.
在特定情况下,Polygon
,Rectangle
,和Triangle
每个人都有一个vtbl
,每一个条目指向其相关area
方法.你ppoly1
将有vptr
指向Rectangle
的vtbl
,并ppoly2
同样用Triangle
的vtbl
.希望这可以帮助!
Chris Jester-Young给出了这个问题的基本答案.
维基百科有更深入的处理.
如果你想知道这类事物是如何工作的全部细节(以及所有类型的继承,包括多重和虚拟继承),最好的资源之一是Stan Lippman的" Inside the C++ Object Model ".