一、前言
好吧,本系列博客已經變成了《C++ Primer Plus》的讀書筆記,尷尬。在使用C語言時,多通過添加庫函數的方式實現代碼重用,但有一個弊端就是原來寫好的代碼並不完全適用於現在的情況。OOP設計思想中類的繼承相比來說更為靈活,可以添加新的數據成員和方法,也能修改繼承下來方法的實現細節,同時還保留了原有的代碼。開始進入正題。
二、類繼承示例
場景如下:現需要記錄乒乓球運動成員的信息,包括姓名和有無空余桌台。其中有一部分成員參加過比賽,需要將這一部分單獨提出並記錄他們在比賽中的比分。因此,參加過比賽的成員所屬的類就是素有成員所屬類的派生類對象了。
類聲明:

1 #ifndef TABTENN_H_ 2 #define TABTENN_H_ 3 4 #include <string> 5 6 using std::string; 7 8 class TableTennisPlayer 9 { 10 private: 11 string firstname; 12 string lastname; 13 bool hasTable; 14 15 public: 16 TableTennisPlayer (const string& fn = "none", 17 const string& ln = "none",bool ht = false); 18 void Name() const; 19 bool HasTable() const {return hasTable;}; 20 void ResetTable(bool v) {hasTable = v;}; 21 }; 22 23 //derived class 24 class RatedPlayer:public TableTennisPlayer //TableTennisPlayer是基類 25 { 26 private: 27 unsigned int rating; 28 public: 29 RatedPlayer(unsigned int r = 0,const string& fn = "none",const string& ln = "none", 30 bool ht = false);//默認構造函數 31 RatedPlayer(unsigned int r,const TableTennisPlayer& tp);//通過基類對象創建派生類對象構造函數 32 unsigned int Rating() const {return rating;} 33 void ResetRating (unsigned int r) {rating = r;} 34 }; 35 36 #endif
類方法定義:

1 #include <iostream> 2 #include "tabtenn.h" 3 4 TableTennisPlayer::TableTennisPlayer (const string& fn,const string& ln,bool ht): 5 firstname(fn),lastname(ln),hasTable(ht)//成員初始化列表 6 {} 7 8 void TableTennisPlayer::Name() const 9 { 10 std::cout << lastname << ", " << firstname; 11 } 12 13 //RatedPlayer methods 14 //派生類構造函數必須調用基類構造函數 15 RatedPlayer::RatedPlayer(unsigned int r,const string& fn,const string& ln,bool ht): 16 TableTennisPlayer(fn,ln,ht)//派生類構造函數首先創建基類對象,使用初始化列表完成 17 { 18 rating = r; 19 } 20 21 RatedPlayer::RatedPlayer(unsigned int r,const TableTennisPlayer& tp): 22 TableTennisPlayer(tp),rating(r) 23 {}
上述代碼將基類TableTennisPlayer和派生類RatedPlayer放在了一起。RatedPlayer類聲明中使用:public name_of_base_class 表示公有派生。在派生類的聲明中要添加自己的構造函數和額外的成員函數和方法。這里派生類構造函數中學問很大。
在創建派生類對象之前必須先創建基類對象,這是因為派生類的方法無法直接訪問基類的私有成員。那問題來了:當創建新的派生類對象時,會自動調用派生類構造函數。如何實現在調用派生類構造函數之前就調用基類構造函數創建基類對象呢?(好繞口)這里需要使用構造函數的特有語法——初始化列表。在程序指針指向派生類構造函數大括號內第一行之前即在初始化列表中完成了基類構造函數的調用。為了方便從基類對象中直接選出派生類對象(基類對象包含派生類對象),使用第二個構造函數,直接為基類對象添加比分信息獲得。
三、應用程序示例
應用程序代碼:

1 #include <iostream> 2 #include "tabtenn.h" 3 4 using std::endl; 5 using std::cout; 6 7 int main() 8 { 9 TableTennisPlayer player1("Tara","Boomdea",false);//創建基類對象 10 RatedPlayer rplayer1(1140,"Mallory","Duck",true);//創建派生類對象 11 player1.Name(); 12 if(player1.HasTable()) 13 cout << ": has a table.\n"; 14 else 15 cout << ": hasn't a table.\n"; 16 rplayer1.Name(); 17 if(rplayer1.HasTable()) 18 cout << ": has a table.\n"; 19 else 20 cout << ": hasn't a table.\n"; 21 22 //initialize RatedPlayer using TableTennisPlayer object 23 RatedPlayer rplayer2(1212,player1); 24 cout << "Name: "; 25 rplayer2.Name(); 26 cout << ";Rating: " << rplayer2.Rating() << endl; 27 return 0; 28 }
player和rplayer分別代表基類對象和派生類對象。rplayer2和player1其實是同一個人,本來參加過比賽的成員就是從所有成員中挑選出來的。應用該程序比較簡單,這里就不過多描述了。