繼承機制是面向對象程序設計使代碼可以複用的最重要的手段,它允許程序員在保持原有類性質的基礎上進行擴展,增加功能。
繼承的定義的格式:
class 派生類名:繼承類型 基類名
繼承類型包括有:public(公有繼承)
private(私有繼承)
protected(保護繼承)
繼承關係 基類的public成員 基類的private成員 基 類 的protected成員 繼承引起的訪問控制變化 public public成員 不可見 protected成員 非私有成員在子類中的訪問屬性不變 private private成員 不可見 private成員 非私有成員在子類中的訪問屬性變爲private屬性 protected protected成員 不可見 protected成員 非私有成員在子類中的訪問屬性變爲protected屬性 舉例:
#include <iostream>
using namespace std;
class A
{
public:
int f1();
private:
int i1;
protected:
int j1;
};
int A::f1()
{
cout << "函數f1的實現" << endl;
}
class B :public A
{
public:
int f2()
{
j1 = 0;
i1 = 0;
cout << "函數f2的實現" << endl;
}
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M01/7E/DA/wKioL1cLJTmzCnBGAABz9WRMrMI523.png" title="無標題.png" alt="wKioL1cLJTmzCnBGAABz9WRMrMI523.png" />在公有繼承的子類中,不能訪問基類中的private成員。因爲基類和子類是兩個不同的類域,private成員只能在類能訪問。
私有繼承和保護繼承也是一樣。
注意:不管是哪種繼承方式,在派生類中都可以訪問基類的公有成員和保護成員,基類的私有成員存在,但在子類中不能訪問。
4. 關鍵字class繼承時,缺省繼承類型則默認爲:private.
關鍵字struct繼承時,缺省繼承類型則默認爲:public.
5. 繼承關係中構造函數的調用順序:
基類構造函數------>派生類中對象的構造函數--------->派生類構造函數體
舉例:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
a = 0;
cout << "A's default constuctor called." << endl;
}
private:
int a;
};
class B :public A
{
public:
B()
{
b = 0;
cout << "B's default constuctor called." << endl;
}
private:
int b;
};
int main()
{
B bb;
system("pause");
return 0;
}
6. 繼承關係中析構函數的調用順序:
派生類析構函數體------>派生類對中析構函數--------->基類構造函數
說明:
基類沒有缺省構造函數,派生類必須要在初始化列表中顯式給出基類名和參數列表;
基類沒有定義構造函數,則派生類也可以不用定義,全部使用缺省構造函數;
基類定義了帶有形參表構造函數,派生類就一定定義構造函數。
7.關於繼承體系中的作用域:
在繼承體系中基類和派生類是兩個不同的作用域,如果子類中有與基類同名的成員,子類成員屏蔽基類對成員直接訪問。
注:在子類成員函數中,可以使用 基類名::基類成員名 這樣的方式類訪問。
舉例:
#include <iostream>
using namespace std;
class A
{
public:
int temp;
private:
int a;
};
class B :public A
{
public:
int temp;
int add()
{
temp = 100;
A::temp = 0;
return temp;
}
private:
int b;
};
int main()
{
B bb;
int ret = 0;
ret = bb.add();
system("pause");
return 0;
}
將子類B中的temp賦值爲100,基類中的temp賦值爲0;
8. 繼承中的賦值兼容規則:
子類對象可以賦值給基類對象,反之不可以;
基類對象的指針/引用可以指向基類對象,子類對象的指針/引用可以通過強制類型轉換的方式指向基 類對象,但是有內存泄漏的風險。
9. 友元與繼承
友元關係不能繼承,基類的友元不能訪問子類的私有和保護成員。
舉例:
#include <iostream>
using namespace std;
class A
{
friend class C;
public:
int temp;
private:
int a;
};
class B :public A
{
public:
int temp;
private:
int b;
protected:
int i;
};
class C
{
public:
int c;
int f()
{
temp = 2;
i = 0;
return 0;
}
};
int main()
{
C bb;
int ret = 0;
ret = bb.f();
system("pause");
return 0;
}
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M00/7E/DB/wKioL1cLNGDzCzD9AABy8wIiKgU019.png" title="無標題3.png" alt="wKioL1cLNGDzCzD9AABy8wIiKgU019.png" />10. 單繼承:一個子類只有一個基類
11. 多繼承:一個子類有多個基類,
定義形式:class 子類名:繼承類型 基類名<,繼承類型 基類名,繼承類型 基類名,...>
12. 菱形繼承:
定義形式:
舉例:
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M02/7E/DB/wKioL1cLNbXzjyJvAAAzrmi1vU0992.png" title="Image [9].png" alt="wKioL1cLNbXzjyJvAAAzrmi1vU0992.png" />發現問題:Assistant的對象中存在兩份Person成員,菱形繼承中存在二義性和數據冗餘的問題。
虛繼承可以解決了菱形繼承中二義性和數據冗餘的問題,但是一般不適用虛繼承,因爲虛繼承帶來了性能上的損耗。
說明:C++語言規定,虛基類子對象是由最派生類的構造函數通過調用虛基類的構造函數進行初始化的。如果一個派生類有一個直接或間接的虛基類,那麼派生類的構造函數的成員初始列表中必須列出對虛基類構造函數的調用;如果未列出,則表示使用該虛基類的默認構造函數來初始化派生類對象中的虛基類子對象。