探解c++多态

对c++多态的探解
什么是多态呢?请看如下程序

例1
class Base
{
public :
     virtual void func()=0;
};

class Drive1 : public Base
{
     public :
     virtual void func()
     {
          cout<<"Drive1::func"<<endl;
     }

};

class Drive2 : public Base
{
public :
     virtual void func()
     {
        cout<<"Drive2::func"<<endl;
     }
};

int main(int argc, char **argv)
{
     int i;
     Base *p[1];
     p[0] = new Drive1();
     p[1] = new Drive2();
     for(i = 0; i < 2; i++)
     {
        p[i]->func();
     }
     return 0;
}
//output
Drive1::func
Drive2::func
这就是多态。 c++中的多态通常是用虚函数实现的,但也有中template技术实现的,ATL中就是用template的技术实现了多态。就性能上说,用虚函数的方法,程序的性能会相对较差点。那么编译器到底悄悄做了什么呢?请看小马哥翻译的 “ATL布幔之下的秘密”http://www.vckbase.com/document/viewdoc/?id=1350。完了再往下看。我们知道当类中有虚函数的时候,编译器会偷偷给类加上一个vfptr指针,指针指向一个vtable,vtable中虚函数的地址。不信?请看vs给的图。
有类:
class Foo
{
public :
virtual void func() {}
public :
   int a;
};

产生一个对象 Foo f


那么定义一个Foo的指针会是什么情况呢? 请看-> Foo *p

同样,Foo类型的指针指向的内存块也有vfptr和成员变量a,只是没有”初始值“。所以可以猜想,当把派生类的指针赋给父类指针的时候,派生类的基类子对象里的vfptr会赋值给基类指针的vfptr,从而实现了多态的行为。

请看例1的程序,调试截图。

那么多重继承的情况又是如何?考虑如下程序

#include <iostream>
using namespace std;

class Base1
{
public :
      virtual void func()=0;
};
class Base2
{
public :
      virtual void func()=0;
};

class Drive : public Base1, public Base2
{
public :
      virtual void func()
      {
            cout<<"Drive::func"<<endl;
      }
};

int main(int argc, char **argv)
{
     Base1 *p1 = new Drive;
       Base2 *p2 = new Drive;
      p1->func();
      p2->func();
      return 0;
}

多重继承情况下,派生类的对象里会有连个vfptr,排放的顺序和继承的顺序相关。

当把派生类的指针赋值给p2的时候,好心的编译器又会偷偷的加上些东西。由于派生类的Base2子对象的vfptr排在Base1子对象的vfpt的后边,所以就会有一个偏移量--4个字节,(因为指针是一个32的整数,4*8)。当Base2 *p2 = new Drive;时,new返回的指针会加上4再赋值给p2,编译器都为我们做好了。

看图

里边的[thunk]:Drive::func`adjustor{4}`就为4个字节的偏移量,thunk结构由编译器维护。具体结构挺复杂,有待研究。

现在,相信你对c++会有新的认识了吧。c++的编译器太好心了,总是偷偷的,默默无闻的为我们操心。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值