C 菱形繼承

2021-10-08 15:30:10 字數 3322 閱讀 7312

1、多重繼承的問題:在c++類的繼承中會遇到這樣乙個問題,乙個派生類有兩個或者兩個以上的基類,如同下面這種繼承情況

類c繼承了類a和類b,但是類a和類b裡面有著相同的成員變數,那麼類c在使用這個成員變數的時候就會出現二義性的問題,需要通過域成員運算子進行區分

class a 

~a(){}

void display()

protected:

uint32_t data_ = 10;

};class b

~b() {}

void display()

protected:

uint32_t data_ = 11;

};class c :public a, public b

~c(){}

void show()

};

2、菱形繼承的問題,假設上面的類a和類b又繼承乙個公共的類base,就會出現下面這種情況

這個時候仍然會存在二義性,二義性是由於他們有公共的基類造成的,比如下面這個例子:

class base 

~base(){}

void display()

protected:

uint32_t data_ = 11;

};class a: public base

~a(){}

protected:

uint32_t data_a_ = 10;

};class b : public base

~b() {}

protected:

uint32_t data_b_ = 11;

};class c :public a, public b

~c(){}

void show()

};

出現二義性的原因就是類a和類b都繼承了類base的成員和函式 ,而且會在類c中存在兩份基類base,會浪費空間

3、為了解決上訴問題,c++引入了虛基類,虛繼承是一種機制,類通過虛繼承指出它希望共享虛基類的狀態。對給定的虛基類,無論該類在派生層次中作為虛基類出現多少次,只繼承乙個共享的基類子物件,共享基類子物件稱為虛基類

class base 

~base() {}

void display()

protected:

uint32_t data_ = 11;

};class a : virtual public base

~a() {}

protected:

uint32_t data_a_ = 10;

};class b : virtual public base

~b() {}

protected:

uint32_t data_b_ = 12;

};class c :public a, public b

~c() {}

void show()

};

可以看到,虛基類可以解決菱形繼承二義性的問題,可以直接讓c類使用base類的成員變數和函式

4、面試過程中被遇到的關於菱形繼承的問題

class base 

~base() {}

virtual void print()

};class a : public base

~a() {}

virtual void print()

virtual void show()

};class b : public base

~b() {}

virtual void print()

virtual void show()

};class c :public a, public b

~c() {}

virtual void show()

virtual void display()

};

虛函式表:其實這個時候使用sizeof(c)計算c的大小,會發現c的大小是8,因為這個時候的c有兩個虛函式表,分別是a的和b的,並且c重寫了對應的虛函式,那麼這個時候c的虛表應該是下面這個樣子的

會不會有問題:不會有問題的,完全正常

class a 

~a(){}

virtual void show()

};class b

~b() {}

virtual void show()

};class c :public a, public b

~c() {}

};int main(void)

答案:仍然是會報二義性的錯誤

解決辦法:

加上作用域去呼叫

c c;

c.a::show();

c.b::show();

使用多型的思想,基類指標,子類物件

a* test = new c();

test->show();

class a 

~a() {}

virtual void print()

virtual void show()

};class b

~b() {}

virtual void print()

virtual void show()

};class c :public a, public b

~c() {}

virtual void show()

virtual void display()

};

其實如果我們計算sizeof(c)的大小會發現是8,為什麼呢?因為它有兩個指標,分別指向兩個虛表, 類c的記憶體結構會是下面這樣

可以看到它將自己的虛函式,放在了第乙個虛表中,原因是和它的繼承順序有關係 

5、參考文件

C 菱形繼承

在c 繼承體系中,有一類問題是永遠跑不掉的即菱形繼承問題。此類問題又被稱作鑽石繼承問題,只是一種較差的設計結構,剛好看到這個問題,特此總結一下。先來看一下菱形繼承的基本結構 a和b從基類base中繼承,而d多重繼承於a,b。那就意味著d中會有base中的兩個拷貝。因為成員函式不體現在類的記憶體大小上...

c 菱形繼承

單繼承 乙個子類只有乙個父類時稱為單繼承 多繼承 乙個子類有兩個或者兩個以上時這個繼承關係為多繼承 菱形繼承是多繼承的一種特殊情況 在繼承中子類會繼承父類的所有的成員,可以看出菱形繼承有資料冗餘和二義性的問題。assistant中會有person的兩份資料。可以從上面看出來我們的assistant中...

C 菱形繼承

菱形繼承概念 1.兩個派生類繼承同乙個基類 2.又有某個類同時繼承著兩個派生類 這種繼承被稱為菱形繼承,或者鑽石繼承 舉個例子 菱形繼承問題 1.羊繼承了動物的資料,鴕同樣繼承了動物的資料,當羊駝使用資料時,就會產生二義性 2.羊駝繼承自動物的資料繼承了兩份,其實我們應該清楚,比如年齡這份資料我們只...