• 浅谈虚继承


    一、提出问题。

    有以下代码。

    class B
    {
    public:
             int a;
    };
    
    class D1 : public B
    {
    public:
             int b;
    };
    
    class D2 : public B
    {
    public:
             int c;
    };
    
    class E :  public D1, public D2
    {
    public:
             int d;
    };
    

    其类图为,

    B

    int a                                                                                             4

    D1

    B::a , int c                                                                                    8

    D2

    B::a , int d                                                                                   8

    E

    D1::B::a , D1::int b , D2::B::a , D2:: int c , int e                          20

    通过分析内存形态我们发现E中基类B被重复继承了,显然我们不想要这种结果。继续验证一下。

    用基类的指针指向子类的对象。

             D1 * pd1 = new D1();
             B * pb = pd1;
    

      基类指针指向了D1的对象,也就是:D1的对象,是一种B。这样是可以的。

          E pe = new E();
    
             D1 * pd1 = pe;      //ok 
    
             D2* pd2 = pe;       //ok
    
             B* pb = pe;        //error 从E到B转换不明确
    

    二、引入虚继承

    以上代码中,我们使用虚继承的方式。

    class D1 : virtual public B

    class D2 : virtual public B

    使用类图表示


    对于程序员来说,这种类层次图显得更加简单和清晰,不过对于一个编译器来说,这就复杂得多了。

    B

    int a                                          

    4

    D1

    B::a , int c , vtbl B         

    12

    D2

    B::a , int d , vtbl B                                      

    12

    E

    B::a , D1::int b , D2:: int c , int d,  vtbl D1, vtbl D2          

    24

    从这里我们看出,子类E每继承一个虚继承的类,都会多使用一个虚表来标记,也就会多占4个字节。

    此时我们再验证一下

    E* pe = new E();
    B* pb = pe;  ///ok

    虚继承一般会用在菱形的继承结构里面。

  • 相关阅读:
    N天学习一个linux命令之lsof
    N天学习一个linux命令之ps
    N天学习一个linux命令之yum
    N天学习一个linux命令之rsync
    N天学习一个linux命令之ss
    N天学习一个linux命令之netstat
    N天学习一个linux命令之vmstat
    N天学习一个linux命令之sort
    N天学习一个linux命令之rpm
    跨域问题
  • 原文地址:https://www.cnblogs.com/flysnail/p/2577831.html
Copyright © 2020-2023  润新知