菱形虛擬繼承

單繼承

一個子類只有一個直接父類時稱這個繼承關係爲單繼承。

class Person
{
public:
    void setinfo(int _age, const char *_name)
    {
        age = _age;
        name = _name;
    }

protected:
    int age;
public:
    string name;
};

class Student:public Person
{
public:
    void setinfo(int _age, const char *_name, int _num)
    {
        Person::setinfo(_age, _name);
        num = _num;
    }
protected:
    int num;
};

多繼承

一個子類有兩個或以上直接父類時稱這個繼承關係爲多繼承

class Student
{
protected :
   int _num ;
   string _name;
};
class Teacher : public Person
{
protected :

    int _id ;

};
class Assistant : public Student, public Teacher
{
protected :
    string _majorCourse ;
};

菱形繼承

菱形繼承就是對單繼承和多繼承的一個組合

class Person
{
public :
    string _name ; // 姓名
};
class Student : public Person
{
protected :
    int _num ; //學號
};
class Teacher : public Person
{
protected :
    int _id ; // 職工編號
};
class Assistant : public Student, public Teacher
{
protected :
    string _majorCourse ; // 主修課程
};

Student 和Teacher類是對Person類的單繼承,而Assistant類則是多繼承前兩者。
這裏寫圖片描述

lass A
{
public:
    int _a;
};

class B1:public A
{

public:
    int _b;
};
class B2 :public A
{
public:
    int _c;
};
class D :public B1, public B2
{
public:
    int _d;
};

void test()
{
    D d;
    //d._a= 0;
    d._b = 1;
    d._c = 2;
    d._d = 3;
}

int main()
{
    test();
    return 0;

}

這裏寫圖片描述
這裏寫圖片描述

這裏寫圖片描述

但是由派生類模型我們可以看到,Assistant類中有兩個Person成員,在對象d的內存中也可以看到由兩個隨機值,這就存在二義性和數據冗餘的問題。

爲了解決菱形繼承中的二義性問題,我們引入了虛擬繼承。

class A
{
public:
    int _a;
};

class B:virtual public A
{

public:
    int _b;
};

void test()
{
    B b;
    b._a = 1;
    b._b = 2;
}

int main()
{
    test();
    return 0;

}

從我們學習到的普通繼承知識,我們知道,如果是普通繼承的話,派生類對象d的大小應該爲8,因爲只有基類的成員變量_a和派生類自己的的成員_b,
這裏寫圖片描述

這裏寫圖片描述

並且和普通繼承不同,普通繼承派生類模型是基類在上,派生類在下,這裏是基類在下,派生類在上,並且在前面多了四個字節的內容,我們把這個類容當作地址再次
這裏寫圖片描述
在這個多了兩個數,一個0一個8,我們在上面的代碼中在派生類中添加一個變量,_b,

lass B:virtual public A
{

public:
    int _b;
    int _b1;
};

這裏寫圖片描述

從這裏我們可以看出,這個0是派生類對於自己的偏移量,因爲不管你類的內容怎麼改變這個0都不變,但是下面那個數字會隨着你派生類的大小而改變,下面的數是派生類和基類的偏移量,我們把他叫做偏移量表格,

所以,在虛擬繼承中,有一個指向偏移量表格的偏移地址,

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;

class B
{
public:
    int _b;
};

class C1 :virtual public B
{
public:
    int _c1;
};

class C2 :virtual public B
{
public:
    int _c2;
};

class D :public C1, public C2
{
public:
    int _d;
};

void Test1()
{
    D d1;
    cout << sizeof(D) << endl;
    d1._c1 = 0;
    d1._c2 = 1;
    d1._d = 2;
    d1._b = 3;
}

int main()
{
    Test1();
    system("pause");
    return 0;
}

這裏寫圖片描述
這裏有兩個偏移地址,
0x012bcb04
這裏寫圖片描述
0x012bcf70
這裏寫圖片描述
一開始運行程序時遇到的_b不明確的問題也沒有出現了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章