虚拟继承解决菱形继承带来的二义性问题的过程详析

 二义性问题请详细看:

http://blog.csdn.net/lxp_mujinhuakai/article/details/69414277
解决上篇文章的问题看一下以下代码:

#include<iostream>
using namespace std;

class Grandam
{
public:
     void introduce_self()
    {
        cout << "I am grandam." << endl;
    }
};

class Mother :virtual public Grandam
{
public:
    void introduce_self()
    {
        cout << "I am mother." << endl;
    }
};

class Aunt :virtual public Grandam
{
public:
    void introduce_self()
    {
        cout << "I am aunt." << endl;
    }
};

class Daughter :public Mother,public Aunt
{
public:
    void introduce_self()
    {
        cout << "I am daughter." << endl;
    }
};

int main()
{
    Grandam* ptr;
    Daughter d;
    ptr = &d;
    ptr->introduce_self();
    return 0;
}

结果如下图所示:

这里写图片描述
我们可以查看对象的内存,来知道内存里存放的具体数字:

,在ptr=&d处打断点,在程序运行到此处时,在内存窗口中打印&d,这样就可查看对象d的内存*,如图所示:*
这里写图片描述

内存的首地址中存储了一个地址,我们在内存中输入这个地址0x00eadc98,再次查看这个地址存放的是什么,如图所示:

这里写图片描述

可以看出前两行的第一行存放的是基类对象基于基类的偏移量,为0。而第二行存放的是该派生类对象d基于基类的偏移量8。下面就总结处虚拟继承的具体实现过程。


对象怎么知道调用的是哪个成员,具体过程如下:
1. 指针或引用知道你调用了哪个对象;
2. 对象可以得到存放基于基类的偏移量的地址;
3. 通过该地址获得基于基类的偏移量;
4. 从而基类对象的this指针加上该偏移量,便可以区分调用的是哪个派生类对象的哪个成员。

注意:
1. 加上关键字virtual后,便会为该派生类对象多开辟4个字节出来,存放基于基类的偏移量的地址(即第2步出现的)。
2. 加上关键字virtual后,该菱形继承的大小只多了4个字节,而不是8个。因为基类的成员只开辟了一个空间。
3.解决二义性问题必须在两个派生类第一次继承基类时的位置的继承方式前加上关键词virtual。

猜你喜欢

转载自blog.csdn.net/lxp_mujinhuakai/article/details/69427582
今日推荐