這是關于一個普通雙非本科大一學生的C++的學習記錄貼
在此前,我學了一點點C語言還有簡單的數據結構,如果有小伙伴想和我一起學習的,可以私信我交流分享學習資料
那么開啟正題
今天分享的是關于繼承的知識點
1.菱形繼承
我們有許多關于繼承的方式
1.單繼承
一個子類只有一個直接父類稱這個繼承關系為單繼承
class A
{
public:int _a;
};class B : public A
{
public:int _b;
};class C : public B
{
public:int _c;
};
2.多繼承
一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承
class A
{
public:int _a;
};class B
{
public:int _b;
};class C : public A, public B
{
public:int _c;
};
3.菱形繼承
菱形繼承是多繼承的一種特殊情況
class A
{
public:int _a;
};class B : public A
{
public:int _b;
};class C : public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};
菱形繼承的問題:菱形繼承有數據冗余和二義性的問題,如上面的D對象中會出現兩份_a成員
2.菱形虛擬繼承
引出了菱形繼承的問題,我們必然有解決的辦法,下面介紹辦法及菱形虛擬繼承
class A
{
public:int _a;
};class B : virtual public A
{
public:int _b;
};class C : virtual public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};
上面就是一種最簡單的菱形虛擬繼承的模型
虛擬繼承可以解決菱形繼承的二義性和數據冗余的問題,如上面的繼承關系,在B,C繼承A的時候使用虛擬繼承即可,需要注意的是,虛擬繼承不要在其他的地方去使用
3.虛擬繼承解決數據冗余和二義性的原理
class A
{
public:int _a;
};class B : virtual public A
{
public:int _b;
};class C : virtual public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};
我們再次借助這個模型來了解虛擬繼承的原理
在vs環境下進入調試,內存窗口中我們可以發現,_a在對象內存的最下面,屬于B,C公共的成員,
那么如果我們將D切割給B(C),此時B(C)如何找到A呢?
這里是通過了B和C內的兩個指針,指向的一張表,這兩個指針叫做虛基表指針,虛基表中存的是偏移量,通過偏移量可以找到下面的A
4.繼承的總結與反思
1.C++語法復雜,多繼承就是一個體現,有了多繼承,就存在菱形繼承,因而有菱形虛擬繼承,底層實現就很復雜
2.多繼承可以認為是C++的一種缺陷,Java就沒有多繼承
3.繼承和組合
繼承是一種is_a的關系,也就是說每一個派生類對象都是一個基類對象
組合是一種has_a的關系,假如B組合了A,每個B對象中都有一個A對象
實際中,優先使用對象組合,而不是類繼承(組合的耦合度低,代碼維護好)
當然有些情況更適用于使用繼承,那么使用繼承也無可厚非
新手寫博客,有不對的位置希望大佬們能夠指出,也謝謝大家能看到這里,讓我們一起學習進步吧!