解析动态联编(下篇) - 作者:tingya,解析动态联编(下篇) - 作者:tingya
【 tulaoshi.com - C语言心得技巧 】
//4.cpp15. #include <iostream.h 16. class shape{17. public:18. virtual void draw(){cout<<"shape::draw()"<<endl;}19. virtual void area(){cout<<"shape::area()"<<endl;}20. void fun(){draw();area();}21. };22. class circle:public shape{23. public:24. void draw(){cout<<"circle::draw()"<<endl;}25. void adjust(){cout<<"circle::adjust()"<<endl;}26. };27. main(){28. shape oneshape;29. oneshape.fun();30. 31. circle circleshape;32. shape& baseshape=circleshape;33. baseshape.fun();34. }编译器在编译上面这段代码的时候将为这shape和circle两个对象分别建立一个VTABLE表,这些表依次填充派生类对象和基类对象中声明的所有的虚函数地址。如果派生类本身没有重新定义基类的虚函数,那么填充的就是基类的虚函数地址。这样一旦如果函数调用一个派生类不存在的方法时候能够自动调用基类方法。然后编译器在每个类中放置一个vptr,一般置于对象的起始位置,继而在对象的构造函数中将vptr初始化为本类的VTABLE的地址。整个结果布局如下。
circle circleshape;shape& baseshape=circleshape;baseshape.fun();函数进入fun函数之后,函数的this指针将指向basefun对象,另一方面basefun指向一个circleshape,因此this指针指向的实际上为circleshape对象,而circleshape的vptr指针指向circle类的虚拟函数表,这样编译器将从虚拟表中取出circle::draw()和circle::area()的地址,进行连接。因为circle本身没有重新定义area()方法,因此编译器使用shape的area()方法。如图四。
来源:http://www.tulaoshi.com/n/20160129/1485504.html
看过《解析动态联编(下篇) - 作者:tingya》的人还看了以下文章 更多>>