繼承就是利用原來聲明的類作爲基礎,再加上新的內容,以減少重複的工作量
- 一個派生類只從一個基類派生叫做單繼承
- 一個派生類有兩個或多個基類的叫做多重繼承
- 繼承和派生的關係可以表述爲派生類是繼承的具體化,而基類是派生類的抽象
聲明派生類的一般形式爲:
class 派生類名:[繼承方式]基類名
{
派生類新加的成員
};
繼承方式包括:public,private和protected
構成一個派生類應該包含以下3部分:
- 從基類接收成員,派生類把基類全部的成員(不包括構造函數和析構函數)接收過來
- 調整從基類接收的成員,可以改變基類成員在派生類中的訪問屬性等
- 在聲明派生類時增加的成員,體現了派生類對基類功能的擴展
派生類的訪問屬性:
-
公用繼承
基類的公有成員和保護成員在派生類中保持其原有訪問屬性,其私有成員仍爲基類私有(不可訪問) -
私有繼承
基類的公有成員和保護成員在派生類中成了私有成員,其私有成員仍爲基類私有 -
受保護的繼承
基類的公有成員和保護成員在派生類中成了保護成員,其私有成員仍爲基類私有。保護成員的意思是,不能被外界引用,但可以被派生類的成員引用
注:保護成員可以被派生類的成員函數引用
多級派生
類A爲基類,類B爲類A的派生類,類C爲類B的派生類,此時類B稱爲類A的直接派生類,類C稱爲類A的間接派生類
派生類構造函數:
一般形式,
派生類構造函數名(總參數表):基類構造函數名(參數表)
{
派生類中新增數據成員初始化語句
}
注意:這裏不是定義基類構造函數,而是調用基類構造函數,因此這些參數是實參而不是形參,可以是常量,全局變量和派生類構造函數總參數表中的參數
有子對象的派生類構造函數:
Student s1;//Student是已經聲明的類名,s1是Student類的對象
這時s1是類對象中的內嵌對象,稱爲子對象,即對象中的對象
一般形式:
派生類構造函數名(總參數表):基類構造函數名(參數表),子對象名(參數表)
{
派生類中新增數據成員初始化語句
}
多重繼承派生類的構造函數:
派生類構造函數名(總參數表):基類1構造函數(參數表),基類2構造函數(參數表),基類3構造函數(參數表列)
{
派生類中新增數據成員初始化語句
}
- 多重繼承可能會引起二義性問題
若類A類B是從同一個基類派生的
class N:
{
public:
int a;
void display()
{
cout<<A::a="<<a<<endl;
};
class A:public N
{
public:
int a1;
};
class B:public N
{
public:
int a2;
};
class C:public A,public B
{
public:
int a3;
void show()
{
cout<<"a3=“<<a3<<endl;
};
int main()
{
C c1;//定義C類對象
.....
}
若要訪問類A從基類N繼承下來的成員:
應當用c1.A::a=3;c1.A::display();
虛基類
C++提供虛基類,使得在繼承間接共同基類時只保留一份成員
聲明虛基類:
class A
{
...
};
class B:virtual public A
{
...
};
注:虛基類並不是在聲明基類時使用的,而是在聲明派生類時,指定繼承方式時聲明的。
class 派生類名:virtual 繼承方式 基類名
虛基類初始化:
class A//定義基類A
{
A(int i){}//基類構造函數且有一個參數
....
};
class B:virtual public A//A作爲B的虛基類
{
B(int n):A(n){}//B類構造函數,在初始化表中對虛基類初始化
....
};
class C:virtual public A
{
C(int n):A(n){}
...
};
class D:public B,public C//D類構造函數,在初始化表中對所有基類初始化
{
D(int n):A(n),B(n),C(n){}
....
};
注:在最後的派生類中,不僅要負責對直接基類進行初始化,還要負責對虛基類初始化
,且C++編譯系統只執行最後的派生類對虛基類的構造函數的調用,而忽略虛基類的其他派生類對虛基類的構造函數的調用,這樣就保證了虛基類的數據成員不會多次被初始化