# 概念
* 在C++中可重用性是通過繼承(inheritance)這一機制來實現的。
* “繼承”就是在一個已存在的類的基礎上建立一個新的類
* 一個新類從已有的類那里獲得其已有特性,這種現象稱為類的繼承。
* 通過繼承,派生類繼承了基類的所有數據成員和絕大多數成員函數(構造函數和析構函數除外),并可以對成員作必要的增加或調整。
* 一個基類可以派生出多個派生類,每一個派生類又可以作為基類再派生出新的派生類,因此基類和派生類是相對而言的。
* 一個派生類有兩個或多個基類的稱為多重繼承(multiple inheritance)。
* 派生類是基類的具體化,而基類則是派生類的抽象。
# **派生**
## **聲明方式**
~~~
class 派生類名: [繼承方式] 基類名
{
派生類新增加的成員
} ;
~~~
### **繼承方式**
* 繼承方式包括: public(公用的),private(私有的)和protected(受保護的)
* 如果不寫此項,則默認為private(私有的)。

## **構成**
* 基類中繼承來的數據成員和成員函數
* 新增的數據成員和成員函數
* 構造函數和析構函數不能繼承,所以需要自己重新寫
## 構造函數
* 派生類所增加的數據成員的初始化
* 基類的數據成員初始化
* 使用冒號語法,對基類數據成員進行初始化
### 順序
① 首先,調用基類構造函數,對基類數據成員初始化;
② 其次,調用子對象構造函數,對對象成員初始化;
③ 最后,執行派生類構造函數本身,對派生類普通數據成員初始化.
### 形式
~~~
派生類構造函數名(總參數表列): 基類構造函數名(參數表列),對象成員名(參數表列)
{
? ?//派生類中新增數據成員的初始化語句
}
~~~
### 例子
~~~
#include <iostream>
#include<string>
using namespace std;
?
class Student //聲明基類Student
{
? ?public: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? Student(int n,string nam,char s) ? ? ? ? ? //基類構造函數
? {
? ? ? num=n;
? ? ? name=nam;
? ? ? sex=s;
? }
? ~Student( ){ } //基類析構函數
? ?protected: ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保護部分
? int num;
? ? ? ?string name;
? char sex ; ? ? ? ? ? ? ? ? ? ? ? ? ? ?
};
class Student1: public Student ? ? //聲明派生類Student1
{
? ?public: ? ? ? ? ? ? ? ? ? ? ? ? ? //派生類的公用部分
? Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s) //派生類構造函數
? {
? ? ? age=a; ? ? ? ? ? ? ? //在函數體中只對派生類新增的數據成員初始化
? ? ? addr=ad;
? }
? void show( )
? {
? ? ? cout<<″num: ″<<num<<endl;
? ? ? cout<<″name: ″<<name<<endl;
? ? ? cout<<″sex: ″<<sex<<endl;
? ? ? cout<<″age: ″<<age<<endl;
? ? ? cout<<″address: ″<<addr<<endl<<endl;
? }
? ~Student1( ){ } //派生類析構函數
? ?private: //派生類的私有部分
? int age; ? ? ? ? ? ? ? ? ? ? ? ? ?
? string addr; ? ? ? ? ? ? ? ?
};
?
int main( )
{
? ?Student1 stud1(10010,″Wang-li″,′f′,19,″115 Beijing Road,Shanghai″);
? ?Student1 stud2(10011,″Zhang-fun″,′m′,21,″213 Shanghai Road,Beijing″);
? ?stud1.show( ); //輸出第一個學生的數據
? ?stud2.show( ); //輸出第二個學生的數據
? ?return 0;
}
~~~
# 多重繼承
一個派生類同時繼承多個基類,稱為多重繼承。
## 形式
~~~
class D:public A,private B,protected C
{
? ?//類D新增加的成員
}
?
//構造函數
派生類構造函數名(總參數表列): 基類1構造函數(參數表列), 基類2構造函數(參數表列), 基類3構造函數 (參數表列)
{
? ?//派生類中新增數成員據成員初始化語句
}
?
?
~~~
## 例子
~~~
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class Teacher //聲明類Teacher(教師)
{
? ?public: //公用部分
? ?Teacher(string nam,int a, string t) ? ? ?//構造函數
? {
? ? ? ?name=nam;
? ? age=a;
? ? title=t;
? }
? ?void display( ) //輸出教師有關數據
? {
? ? ? ?cout<<″name:″<<name<<endl;
? ? ? ?cout<<″age″<<age<<endl;
? ? ? ?cout<<″title:″<<title<<endl;
? }
? ?protected: //保護部分
? ?string name;
? ?int age;
? ?string title; //職稱
};
class Student //定義類Student(學生)
{
? ?public:
? ?Student(char nam[],char s,float sco)
? {
? ? ? ?strcpy(name1,nam);
? ? sex=s;
? ? score=sco;
? } //構造函數
? ?void display1( ) //輸出學生有關數據
? {
? ? ? ?cout<<″name:″<<name1<<endl;
? ? ? ?cout<<″sex:″<<sex<<endl;
? ? ? ?cout<<″score:″<<score<<endl;
? }
? ?protected: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保護部分
? ?string name1;
? ?char sex;
? ?float score; ? ? ? ? ? ? ? ? ? ? ? ? ? ?//成績
};
class Graduate:public Teacher,public Student ?//聲明多重繼承的派生類Graduate
{
? ?public:
? ?Graduate(string nam,int a,char s, string t,float sco,float w)
? ? ? :Teacher(nam,a,t),Student(nam,s,sco),wage(w) { }
? ?void show( ) //輸出研究生的有關數據
? {
? ? ? ?cout<<″name:″<<name<<endl;
? ? ? ?cout<<″age:″<<age<<endl;
? ? ? ?cout<<″sex:″<<sex<<endl;
? ? ? ?cout<<″score:″<<score<<endl;
? ? ? ?cout<<″title:″<<title<<endl;
? ? ? ?cout<<″wages:″<<wage<<endl;
? }
? ?private:
? ?float wage; ? ? ? ? ? ? ? ? ? ? //工資
};
int main( )
{
? ?Graduate grad1(″Wang-li″,24,′f′,″assistant″,89.5,1234.5);
? ?grad1.show( );
? ?return 0;
}
~~~
## 二義性
當基類與派生類之間出現相同的數據成員時,就有二義性
### 解決辦法
~~~
// 指明作用域
//Student和Teacher類中有相同的name數據時
cout<<″name:″<<Teacher::name<<endl; ? //在Student類中調用Teacher類的name
~~~
### 同名覆蓋
* 基類的同名成員在派生類中被屏蔽,成為“不可見”的
* 派生類新增加的同名成員覆蓋了基類中的同名成員。
* 不同的成員函數,只有在函數名和參數個數相同、類型相匹配的情況下才發生同名覆蓋,如果只有函數名相同而參數不同,不會發生同名覆蓋,而屬于函數重載。
# 虛基類
* 使得在繼承間接共同基類時只保留一份成員。
* 虛基類并不是在聲明基類時聲明的,而是在聲明派生類時,指定繼承方式時聲明的
* 在最后的派生類中不僅要負責對其直接基類進行初始化,還要負責對虛基類初始化。
* C++編譯系統只執行最后的派生類對虛基類的構造函數的調用,而忽略虛基類的其他派生類(如類B和類C) 對虛基類的構造函數的調用,這就保證了虛基類的數據成員不會被多次初始化。
## 形式
~~~
class A //聲明基類A
{…};
class B :virtual public A //聲明類B是類A的公用派生類,A是B的虛基類
{…};
class C :virtual public A //聲明類C是類A的公用派生類,A是C的虛基類
{…};
~~~
## 例子
~~~
#include <iostream>
#include <string>
using namespace std;
?
//聲明公共基類Person
class Person
{
? ?public:
? ?Person(string nam,char s,int a)//構造函數
? {
? ? ? ?name=nam;sex=s;age=a;
? }
? ?protected: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保護成員
? ?string name;
? ?char sex;
? ?int age;
};
//聲明Person的直接派生類Teacher
class Teacher:virtual public Person ? //聲明Person為公用繼承的虛基類
{
? ?public: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?Teacher(string nam,char s,int a, string t)
? ? ? :Person(nam,s,a) //構造函數
? ? ? {
? ? ? ? ? ?title=t;
? ? ? }
? ?protected: ? ? ? ? ? ? ?//保護成員
? ?string title; ? ? ? ? ? //職稱
};
?
//聲明Person的直接派生類Student
class Student:virtual public Person ? ? //聲明Person為公用繼承的虛基類
{
? ?public:
? ?Student(string nam,char s,int a,float sco) //構造函數
? ? ? :Person(nam,s,a),score(sco){ } //初始化表
? ?protected: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保護成員
? ?float score; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //成績
};
?
//聲明多重繼承的派生類Graduate
class Graduate:public Teacher,public Student ? //Teacher和Student為直接基類
{
? ?public:
? ?Graduate(string nam,char s,int a, string t,float sco,float w) //構造函數
? ? ? :Person(nam,s,a),Teacher(nam,s,a,t),Student(nam,s,a,sco),wage(w){}//初始化表
? ?void show( ) //輸出研究生的有關數據
? {
? ? ? ?cout<<″name:″<<name<<endl;
? ? ? ?cout<<″age:″<<age<<endl;
? ? ? ?cout<<″sex:″<<sex<<endl;
? ? ? ?cout<<″score:″<<score<<endl;
? ? ? ?cout<<″title:″<<title<<endl;
? ? ? ?cout<<″wages:″<<wage<<endl;
? }
? ?private:
? ?float wage; ? ? ? ? ? ? ? ? ? ? //工資
};
int main( ) //主函數
{
? ?Graduate grad1(″Wang-li″,′f′,24,″assistant″,89.5,1234.5);
? ?grad1.show( );
? ?return 0;
}
~~~
# 繼承與組合
* 在一個類中以某類對象作為數據成員的,稱為類的組合(composition)。
* 繼承是縱向的,組合是橫向的。
- 介紹
- 編程設計語言
- 第一章 對C++的初步認識
- 1.2 最簡單的C++程序
- 1.3 C++對C的補充
- 1.3.1 return
- 1.3.2 輸入輸出流
- 1.3.3 putchar 和 getchar
- 1.3.4 用const定義常變量
- 1.3.5 函數原型聲明
- 1.3.6 內置函數
- 1.3.7 函數重載
- 1.3.8 函數模板
- 1.3.9 有默認值的參數
- 1.3.10 作用域
- 1.3.11 const修飾指針
- 1.3.12 引用
- 1.3.13 生命期
- 1.3.14 變量
- 1.3.15 字符串變量
- 第二章 類與對象
- 2.2 類的聲明和對象的定義
- 2.3 類的成員函數
- 第三章 關于類和對象的進一步討論
- 3.1 構造函數
- 3.1.1 對象的初始化
- 3.1.2 構造函數
- 3.2 析構函數
- 3.3調用析構函數和構造函數的順序
- 3.4 對象數組
- 3.5 對象指針
- 3.6 共享數據的保護
- 3.7 對象的建立與釋放
- 3.8 對象的賦值與復制
- 3.9 靜態成員
- 3.10 友元
- 3.11 類模板
- 第四章 運算符重載
- 數據類型轉換
- 運算符重載
- 重載流插入運算符和流提取運算符
- 第五章 繼承與派生
- 繼承與派生
- 第六章 多態性與虛函數
- 多態性
- 虛函數
- 純虛函數與抽象類