zoukankan      html  css  js  c++  java
  • C++虚继承

    什么是虚继承

    子类在继承父类时,在声明前加virtual关键字,这就是虚继承
    例:

    class A
    {
      //......
    }
    
    class B:virtual public A
    {
      //.......
    }
    

    什么时候需要使用虚继承

    在多重继承时,正常情况下子类对象将拥有继承链上所有父类对应的部分,但是如果两个父类都继承了同一个类,
    那么在子类将拥有两份祖父类的数据,比如菱形继承:
    20190804190545.png

     
    下面我以四个简单类来分析其内存结构:

    class CFuniture
    {
      int m_nFun;
    public:
      CFuniture()
      {
        m_nFun = 0;
      }
    
      virtual ~CFuniture()
      {
    
      }
    
      virtual void FunitureName()
      {
        cout << "CFuniture::FunitureName()" << endl;
      }
    };
    
    
    class CSofa : public CFuniture
    {
      int m_nSofa;
    public:
    
      virtual void Sit()
      {
        cout << "CSofa::Sit()" << endl;
      }
    
      CSofa()
      {
        m_nSofa = 1;
      }
    
      virtual ~CSofa()
      {
        cout << "~CSofa()" << endl;
      }
    };
    
    
    class CBed : public CFuniture
    {
      int m_nBed;
    public:
      CBed()
      {
        m_nBed = 2;
      }
    
      virtual void Sleep()
      {
        cout << "CBed::Sleep()" << endl;
      }
    
      virtual ~CBed()
      {
    
      }
    };
    
    class CSofaBed :public CSofa, public CBed
    {
      int m_nSofaBed;
    public:
      CSofaBed()
      {
        m_nSofaBed = 3;
      }
    
      virtual ~CSofaBed()
      {
        cout << "~CSofaBed()" << endl;
      }
    
      virtual void SleepAndSit()
      {
        cout << "CSofaBed::SleepAndSit()" << endl;
      }
    
      virtual void SitAndSleep()
      {
        cout << "CSofaBed::SitAndSleep()" << endl;
      }
    
      virtual void Sleep()
      {
        cout << "CSofaBed::Sleep()" << endl;
      }
    
      virtual void Sit()
      {
        cout << "CSofaBed::Sit()" << endl;
      }
    };
    
    
    int main(int argc, char **argv)
    {
      CSofaBed sofabed;
      return 0;
    }
    

    这里家具类CFuniture祖父类,沙发类CSofa和床类CBed都继承继承自CFuniture,沙发床类CSofaBed同时继承
    了CSofa和CBed,现在来看看CSofaBed对象的内存布局:
    20190805094512.png
    可以看出祖父类CFuniture在CSofaBed中有两份,这并非我们本意,我只想CSofaBed类对象中只有一份CFuniture
    类数据,那么可以在CSofa和CBed继承CFuniture时,加上virtual关键字表示和其它类共享CFuniture:

    class CSofa :virtual public CFuniture
    class CBed :virtual public CFuniture
    

    此时再来看看CSofaBed对象的内存布局:
    20190805095742.png
    从监视窗口可以看出CFunitrue类的数据有独立的一部分,但是CSofa和CBed中依旧有CFunitrue类的数据,
    其实这是VS的监视窗口为了更直观的显示继承体系,在CSofa和CBed中显示了CFunitrue类的数据,但是从
    内存窗口中可以看出CFunitrue类的数据只有一份;

     
    从上图可以看出CFunitrue类在CSofaBed子类中被独立出来,放在了对象的最尾部内存地址处,因为在CSofa和CBed以及CFunitrue中都有自己的虚函数,所以CSofaBed子类此时拥有三张属于自己虚表(和父类中的虚表不是同一个),另外CSofaBed子类自己新加的虚函数被追加到继承自CSofa虚表的后面,CSofaBed的析构函数被放到
    继承自祖父类CFunitrue的虚表中

     
    还可以从内存布局中看出CSofaBed的两个直接基类的虚表指针后面,还跟着两个指针:0x01259b68和0x01259bbc
    这两个指针是偏移指针,它们两指向相同的结构体,该结构体共8字节,前四个字节无意义,后四个字节记录了偏移
    指针距离CFunitrue类部分的字节数;从上图中可以看出sofbed对象中,CFunitrue类的部分位于0x0044FBDC
    开始的,CSofa类部分的偏移指针在0x0044FBC0处,两者之间间隔了0x18个字节;CBed类部分的偏移指针位于0x0044FBD0处,和CFunitrue类的部分间隔了0x0C个字节

  • 相关阅读:
    Digital Video Stabilization and Rolling Shutter Correction using Gyroscope 论文笔记
    Distortion-Free Wide-Angle Portraits on Camera Phones 论文笔记
    Panorama Stitching on Mobile
    Natural Image Stitching with the Global Similarity Prior 论文笔记 (三)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(二)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(一)
    ADCensus Stereo Matching 笔记
    Efficient Large-Scale Stereo Matching论文解析
    Setting up caffe on Ubuntu
    Kubernetes配置Secret访问Harbor私有镜像仓库
  • 原文地址:https://www.cnblogs.com/UnknowCodeMaker/p/11301378.html
Copyright © 2011-2022 走看看