目錄
- 一,繼承與友元
- 二,繼承與靜態成員
- 三,復雜的菱形繼承及菱形虛擬繼承
- 四,繼承的總結和反思
點擊跳轉上一篇文章: 【C++】:繼承(定義&&賦值兼容轉換&&作用域&&派生類的默認成員函數)
一,繼承與友元
友元關系不能繼承,也就是說基類友元不能訪問子類私有和保護成員 。
二,繼承與靜態成員
基類定義了static靜態成員,則整個繼承體系里面只有一個這樣的成員。無論派生出多少個子類,都只有一個static成員實例 。
class Person
{
public:Person() { ++_count; }
protected:string _name; // 姓名
public:static int _count; // 統計人的個數。
};int Person::_count = 0;class Student : public Person
{
protected:int _stuNum; // 學號
};int main()
{Person p;Student s;cout << &Person::_count << endl;cout << &Student::_count << endl;return 0;
}
在上述代碼中,此時Student和Person里面的_count是同一個,靜態變量_count存在靜態區,不是單獨的存在各個對象里,是屬于整個繼承體系了。
三,復雜的菱形繼承及菱形虛擬繼承
1.單繼承:一個子類只有一個直接父類時稱這個繼承關系為單繼承。
2.多繼承:一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承。
3.菱形繼承:菱形繼承是多繼承的一種特殊情況。
菱形繼承的問題:從下面的對象成員模型構造,可以看出菱形繼承有數據冗余和二義性的問題。
class Person
{
public:string _name; // 姓名int _id;int _tel;string _adress;
};class Student : public Person
{
protected:int _num; //學號
};class Teacher : public Person
{
protected:int _id; // 職工編號
};class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修課程
};int main()
{//數據冗余和二義性Assistant a;//a._name = "小李";//a._name = "李老師";//1.指定類域a.Student::_name = "小李";a.Teacher::_name = "李老師";
}
由監視窗口得出數據的冗余:
在Assistant的對象中Person成員會有兩份。
并且在訪問成員變量時指定不明確,有二義性:
4.解決方法
4.1 訪問成員變量有二義性時,可指定類域。
int main()
{//繼承代碼續接上……//1.指定類域a.Student::_name = "小李";a.Teacher::_name = "李老師";
}
4.2 虛擬繼承可以解決菱形繼承的二義性和數據冗余的問題
虛擬繼承:在繼承會造成冗余的類的那里加上關鍵字 virtual。
class Person
{
public:string _name; // 姓名int _id;int _tel;string _adress;
};class Student : virtual public Person
{
protected:int _num; //學號
};class Teacher : virtual public Person
{
protected:int _id; // 職工編號
};class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修課程
};int main()
{Assistant a;a.Student::_name = "小李";a._name = "小李";a._name = "李老師";return 0;
}
四,繼承的總結和反思
1.很多人說C++語法復雜,其實多繼承就是一個體現。有了多繼承,就存在菱形繼承,有了菱形繼承就有菱形虛擬繼承,底層實現就很復雜。
2.多繼承可以認為是C++的缺陷之一,很多后來的OO語言都沒有多繼承,如Java。
3.繼承和組合
(1) public繼承是一種is-a的關系。也就是說每個派生類對象都是一個基類對象。
(2) 組合是一種has-a的關系。假設B組合了A,每個B對象中都有一個A對象。
(3) 優先使用對象組合,而不是類繼承。
(4) 繼承可以直接訪問基類的protected 和 public成員。在繼承方式中,基類的,內部細節對子類可見 。繼承一定程度破壞了基類的封裝,類的改變,對派生類有很大的影響。派生類和基類間的依賴關系很強,耦合度高。
(5) 組合只能訪問public成員。組合類之間沒有很強的依賴關系,耦合度低。優先使用對象組合有助于你保持每個類被封裝。