c++虚函数实现与this指针

我们知道当我们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。

那么多重继承时是什么情况呢?

多重继承的时候,对于每个有虚函数的基类,子类都会继承相应的虚指针并改写虚表。

  • this指针

我觉得一篇blog写的挺好就引用过来了。博客地址为:http://www.cnblogs.com/CCQLegend/p/3270738.html

this指针跟不少人想象的不一样,它的类型由被调用函数决定。它的类型遵循着这两点规则:(途中打勾为首地址。)

1.对于非虚函数,this指针的基准地址为函数定义所在层级对象的首地址,范围为该层级对象始末。

如:IA::FF();

this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。(其实里面有内存空洞,我们不去纠结这个)

Derived::FF();

this指针类型是C0H为首地址,范围是从首地址到E8H为止。

c++虚函数实现与this指针

2.对于虚函数,this指针的基准地址为函数首先声明者的首地址,范围为实现者的始末。

如:IA::F();

其this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。

Derived::F();

其this指针类型是以D0H为首地址,范围是从C0H到E8H为止。

c++虚函数实现与this指针

那么当有IA* a=new Derived();后,

a->F();便是这么访问b成员的了。假设首地址D0H保存在寄存器rax里,

rax-8

原文链接: https://www.cnblogs.com/coderht/p/7436860.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/258863

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午12:14
下一篇 2023年2月14日 下午12:15

相关推荐