虚继承(C++)

目录

菱形继承

虚继承

虚继承原理

 虚继承使用注意事项:


                          不要把所有的遗憾都留给未来,趁年轻出去走走,

                  让我们用心去感受这个世界,用脚步去丈量这个世界的距离。

这里是来自M--Y的专栏:C++启()航

以下内容均为个人见解,如有不足还请指出

期待大家的点赞、收藏、评论(互三必回)诸君共勉

             

菱形继承

单继承:一个子类只有一父类

                          

多继承:一个子类有两个或者两个以上的直接父类

 菱形继承:菱形继承是一种特殊的情况

      

从上图可以看出类Student和类Teacher都继承了Person,当类Assistant同时继承Student和Teacher,就会有两份Person,由此可见菱形继承会产生数据冗余和二义性的问题。

数据冗余:一个类中存在重复数据

二义性:访问时无法确定准确访问的是哪一个,需要指定访问

因此推出虚继承来解决此类问题

虚继承

class Person
{
public :
        string _name ; // 姓名
};
class Student : virtual public Person
{
protected :
        int _num ; // 学号
};
class Teacher : virtual public Person
{
protected :
        int _id ; // 职工编号
};
class Assistant : public Student , public Teacher
{
protected :
        string _majorCourse ; // 主修课程
};
void Test ()
{
        Assistant a ;
        a . _name = "peter" ;
}

看上图可知虚继承就是在下面子类可能会产生数据冗余和二义性的父类继承前面加一个virtual

虚继承原理

下面是借助内存窗口观察对象成员模型

class A
{
public :
        int _a ;
};
// class B : public A
class B : virtual public A
{
public :
        int _b ;
};
// class C : public A
class C : virtual public A
{
public :
        int _c ;
};
class D : public B , public C
{
public :
        int _d ;
};
int main ()
{
        D d ;
        d . B::_a = 1 ;
        d . C::_a = 2 ;
        d . _b = 3 ;
        d . _c = 4 ;
        d . _d = 5 ;
        return 0 ;
}

 先来观察没有进行虚继承前的内存窗口

          

再观察进行虚继承后的内存窗口

可以看到经过虚继承后D对象将A放到了对象组成成员的最下面,这个A同时属于B和C。

那么B和C是如何去找到公共的A的呢?

其实这里是通过B和C的两个指针,指向同一张表,这两个指针叫虚基表指针(vbptr),这两个表叫虚基表。

虚基表中存的偏移量。这个量就是表的的地址到父类地址的距离。通过偏移量可以找到下面的A。

以B虚基表为例:距离差为F770-F75C=14(16进制)         
                                                

              

 虚继承使用注意事项:

1.当使用虚继承的时候,需要注意,虚继承只有在多继承时才有用。也就是说如果只有一层继承关系或者是单继承都将不起作用。

2.因为虚继承是保证子类中只有一个间接父类,说简单一点就是虚继承只能在隔代继承中起作用

当出现上图情况时,虚继承写在D处,将无法再E中实现虚继承的效果,必须写在B处。 

相关推荐

  1. C++继承

    2024-07-19 18:04:01       34 阅读
  2. C++——继承与菱形继承

    2024-07-19 18:04:01       50 阅读
  3. C++多继承继承

    2024-07-19 18:04:01       20 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 18:04:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 18:04:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 18:04:01       58 阅读
  4. Python语言-面向对象

    2024-07-19 18:04:01       69 阅读

热门阅读

  1. udp和tcp区别

    2024-07-19 18:04:01       23 阅读
  2. Leetcode 383. 赎金信

    2024-07-19 18:04:01       20 阅读
  3. 接口加密方案

    2024-07-19 18:04:01       18 阅读
  4. ubuntu24.04 搭建TFTP服务

    2024-07-19 18:04:01       20 阅读
  5. 39、PHP 实现二叉树的下一个结点(含源码)

    2024-07-19 18:04:01       19 阅读
  6. box-shadow

    2024-07-19 18:04:01       17 阅读
  7. 【理解Python中的字典推导式】

    2024-07-19 18:04:01       18 阅读
  8. Qt 遍历Combbox下拉框的内容并进行判断

    2024-07-19 18:04:01       18 阅读
  9. 数据库存 IP 地址,用什么数据类型比较好?

    2024-07-19 18:04:01       17 阅读
  10. linux报错-bash: ./xx.sh: Permission denied

    2024-07-19 18:04:01       16 阅读
  11. 网络安全等级保护制度是如何分级的?

    2024-07-19 18:04:01       19 阅读
  12. 【Leetcode】14. 最长公共前缀

    2024-07-19 18:04:01       17 阅读