天天看點

複雜的菱形繼承及菱形虛拟繼承

單繼承

一個子類隻有一個直接父類時稱這個繼承關系為單繼承

複雜的菱形繼承及菱形虛拟繼承

多繼承

一個子類有兩個或兩個以上的直接父類時稱這個繼承方式為多繼承

複雜的菱形繼承及菱形虛拟繼承

菱形繼承

菱形繼承的問題

1.備援

2.二義性

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 ; // 主修課程 
};
void Test ()
{
	// 這樣會有二義性無法明确知道通路的是哪一個    
	Assistant a ;
	a._name = "peter";
	// 需要顯示指定通路哪個父類的成員可以解決二義性問題,但是資料備援問題無法解決
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
}
           
// 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;
}
           

繼承的總結與反思

  1. 很多人說C++文法複雜,其實多繼承就是一個展現。有了多繼承,就存在菱形繼承,有了菱形繼承就有 菱形虛拟繼承,底層實作就很複雜。
  2. 多繼承可以認為是C++的缺陷之一。
  3. 繼承群組合

    (1)public繼承是一種is-a的關系。也就是說每個派生類對象都是一個基類對象。

    (2)組合是一種has-a的關系。假設B組合了A,每個B對象中都有一個A對象。

    (3)有限使用對象組合,而不是類繼承

    (4)繼承允許你根據基類類的實作來定義派生類的實作。這種通過生成派生類的複用通常被稱為白箱複 用(white-box reuse)。術語“白箱”是相對可視性而言:在繼承方式中,基類的内部細節對子類可見 。繼承一定程度破壞了基類的封裝,基類的改變,對派生類類有很大的影響。派生類和基類間的依賴關系很強,耦合度高。

    (5) 對象組合是類繼承之外的另一種複用選擇。新的更複雜的功能可以通過組裝或組合對象來獲得。對 象組合要求被組合的對象具有良好定義的接口。這種複用風格被稱為黑箱複用(black-box reuse), 因為對象的内部細節是不可見的。對象隻以“黑箱”的形式出現。 組合類之間沒有很強的依賴關系, 耦合度低。優先使用對象組合有助于你保持每個類被封裝。

    (6)實際盡量多去用組合。組合的耦合度低,代碼維護性好。不過繼承也有用武之地的,有些關系就适 合繼承那就用繼承,另外要實作多态,也必須要繼承。類之間的關系可以用繼承,可以用組合,就 用組合。