fc2共享视频 fc2共享视频

继承机制下的虚函数及动态机制才是真正的面向对象技术,否则充其量也只是基于对象技术 。
【fc2共享视频 fc2共享视频】继承允许把对象作为它自己的类型或它的基类类型处理 。这个能力很重要,因为它允许很多类型(从同一个基类派生的)被等价地看待就像它们是一个类型,允许同一段代码同样地工作在所有这些不同类型上 。虚函数反映了一个类型与另一个类似类型之间的区别,只要这两个类型都是从同一个基类派生的 。这种区别是通过其在基类中调用的函数的表现不同来反映的 。例如,我们可以定义一个基类(包含虚函数)指针或引用做参数,那这个参数便可以是这个基类继承链上的任一子类对象,在基类扩充子类时,这一函数的代码不会受到影响 。
1 虚函数指针及其目标对象(虚函数表)在内存中的相对位置拥有虚函数的类会有一个虚表,而且这个虚表存放在类定义模块的数据段中 。模块的数据段通常存放定义在该模块的全局数据和静态数据,这样我们可以把虚表看作是模块的全局数据或者静态数据 。
类的虚表会被这个类的所有对象所共享 。类的对象可以有很多,但是他们的虚表指针都指向同一个虚表,从这个意义上说,我们可以把虚表简单理解为类的静态数据成员 。值得注意的是,虽然虚表是共享的,但是虚表指针并不是,类的每一个对象有一个属于它自己的虚表指针 。
虚表中存放的是虚函数的地址 。
#include <stdio.h>class A{int m_i;int m_j;public:virtual void f(int a){printf("A:f(%d)\n",a);}virtual void g(double d){printf("A:f(%.2f)\n",d);}};int main(){A *obj = new A;printf("对象指针obj地址:%x\n",&obj);printf("对象指针obj目标对象地址:%x\n",obj);long *vtp = (long *)*((long*)obj);printf("对象指针obj目标对象前4个字节构成的值(虚函数表指针):%x\n",vtp);printf("对象指针obj目标对象虚函数表指针目标虚函数1:%x\n",vtp<0>);printf("对象指针obj目标对象虚函数表指针目标虚函数2:%x\n",vtp<1>);void(*vfp1)(int) = (void(*)(int))vtp<0>;// 虚函数1void(*vfp2)(double) = (void(*)(double))(*(vtp+1));// 虚函数2vfp1(0); // debug模式下可能有关于esp错误信息的提示,因为调用方式不一样vfp2(1);getchar();return 0;}/*对象指针obj地址:12ff38对象指针obj目标对象地址:3128b0对象指针obj目标对象前4个字节构成的值(虚函数表指针):429118对象指针obj目标对象虚函数表指针目标虚函数1:40100f对象指针obj目标对象虚函数表指针目标虚函数2:401005A:f(0)A:f(1.00)*/

fc2共享视频 fc2共享视频

文章插图
fc2共享视频 fc2共享视频

文章插图
fc2共享视频 fc2共享视频

文章插图
fc2共享视频 fc2共享视频

文章插图
ref
Bruce Eckel《Thinking in C++, 2nd ed. Volume 1》
-End-

    推荐阅读