标签:分享 code 输出 入口 blog ima 不同 his int
我们知道当我们sizeof 一个类的时候,类的成员函数是不计算在对象的大小的里的,这是为什么呢?因为类的成员函数不是属于某一个对象的,而是类的所有对象所共享的,就像static变量那样。如果虚函数和普通成员函数一样,那么我们就不能通过指向子类的基类指针来引用子类的方法了,因为我们将不知道调用哪个方法,多态就无从谈起。那么多态是怎么实现的呢?
我们可以做一个小实验
class A{ public: int a; virtual void myfun(){} }; class B:public A{ public: int b; }; B obj_b;
obj_b.a=1;
obj_b.b=2; A *p=&B; cout<<p<<endl; cout<<&(p->a)<<endl;
cout<<p->a<<‘\t‘<<*(&(p->a)+1)<<endl;
p的值和&(p->a)的值是相差4个字节的,最后一行输出的值为1 ,2。我们可以推断出obj_b在内存中的分布是首先一个占有4字节的某类型,然后是int a,最后是int b。
初始的4字节其实就是虚指针。
而类A的对象在内存的分布其实是虚指针然后是int a。
如果类B继承A,在B构造的时候,会继承虚指针和int a,但是虚指针指向的虚表就不同了。若在B中实现了虚函数则虚表中的对应函数的入口地址也会改变。从而达到多态的目的。
注意指针p并访问不到b,因为p是A类型的指针,可见指针的访问范围由的类型决定了。所以我们通过&(p->a)+1来访问b。
那么多重继承时是什么情况呢?
多重继承的时候,对于每个有虚函数的基类,子类都会继承相应的虚指针并改写虚表。
我觉得一篇blog写的挺好就引用过来了。博客地址为:http://www.cnblogs.com/CCQLegend/p/3270738.html
this指针跟不少人想象的不一样,它的类型由被调用函数决定。它的类型遵循着这两点规则:(途中打勾为首地址。)
1.对于非虚函数,this指针的基准地址为函数定义所在层级对象的首地址,范围为该层级对象始末。
如:IA::FF();
this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。(其实里面有内存空洞,我们不去纠结这个)
Derived::FF();
this指针类型是C0H为首地址,范围是从首地址到E8H为止。
2.对于虚函数,this指针的基准地址为函数首先声明者的首地址,范围为实现者的始末。
如:IA::F();
其this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。
Derived::F();
其this指针类型是以D0H为首地址,范围是从C0H到E8H为止。
那么当有IA* a=new Derived();后,
a->F();便是这么访问b成员的了。假设首地址D0H保存在寄存器rax里,
rax-8
标签:分享 code 输出 入口 blog ima 不同 his int
原文地址:http://www.cnblogs.com/coderht/p/7436860.html