新標準C++程序設計讀書筆記_繼承和多態
簡單繼承的例子:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class CStudent 6 { 7 private: 8 string name; 9 string id; //學號 10 char gender; //性別,‘F‘代表女, ‘M‘代表男 11 int age; 12 public: 13 void PrintInfo(); 14 void SetInfo( conststring & name_,const string & id_, 15 int age_, char gender_ ); 16 string GetName() { return name; } 17 }; 18 19 void CStudent::PrintInfo() 20 { 21 cout << "Name:" << name << endl; 22 cout << "ID:" << id << endl; 23 cout << "Age:" << age << endl; 24 cout << "Gender:" << gender << endl; 25 } 26 27 void CStudent::SetInfo( const string & name_,const string & id_, 28 int age_,char gender_ ) 29 { 30 name = name_; 31 id = id_; 32 age = age_; 33 gender = gender_;34 } 35 36 class CUndergraduateStudent : public CStudent 37 { 38 //本科生類,繼承了CStudent類 39 private: 40 string department; //學生所屬的系的名稱 41 public: 42 void QualifiedForBaoyan() 43 { 44 //給予保研資格 45 cout << “qualified for baoyan” << endl; 46 } 47 48 void PrintInfo() 49 { 50 CStudent::PrintInfo(); //調用基類的PrintInfo 51 cout << “Department:” << department <<endl; 52 } 53 54 void SetInfo( const string & name_,const string & id_, 55 int age_,char gender_ ,const string & department_) 56 { 57 CStudent::SetInfo(name_,id_,age_,gender_); //調用基類的SetInfo 58 department = department_; 59 } 60 }; 61 62 int main() 63 { 64 CUndergraduateStudent s2; 65 s2.SetInfo(“Harry Potter ”, “118829212”,19,‘M’,“Computer Science”); 66 cout << s2.GetName() << “ ” ; 67 s2.QualifiedForBaoyan (); 68 s2.PrintInfo (); 69 return 0; 70 }
類之間的兩種關系
(1)繼承:“是”關系。
基類 A, B是基類A的派生類。邏輯上要求:“一個B對象也是一個A對象”。
(2)復合:“有”關系。
類C中“有” 成員變量k, k是類D的對象,則C和D是復合關系,一般邏輯上要求:“ D對象是C對象的固有屬性或組成部分”。
幾何形體程序中,需要寫“點”類,也需要寫“圓”類
1 class CPoint 2 { 3 double x,y; 4 }; 5 6 class CCircle : public CPoint 7 { 8 double r; 9 };
這是不合理的,應該使用復合關系;每一個“圓”對象裏都包含(有)一個“點”對象,這個“點”對象就是圓心
1 class CPoint 2 { 3 double x,y; 4 //便於Ccirle類操作其圓心 5 friend class CCircle; 6 }; 7 8 class CCircle 9 { 10 double r; 11 CPoint center; 12 };
覆蓋
派生類可以定義一個和基類成員同名的成員,這叫覆蓋。在派生類中訪問這類成員時,缺省的情況是訪問派生類中定義的成員。要在派生類中訪問由基類定義的同名成員時,要使用作用域符號“::”
訪問控制符
以下均表示可以被下列函數訪問
1、基類的private成員:
(1)基類的成員函數
(2)基類的友員函數
2、基類的public成員:
(1)基類的成員函數
(2)基類的友員函數
(3)派生類的成員函數
(4)派生類的友員函數
(5)其他的函數
3、基類的protected成員:
(1)基類的成員函數
(2)基類的友員函數
(3)派生類的成員函數可以訪問當前對象的基類的保護成員
1 class Father 2 { 3 private: 4 int nPrivate; //私有成員 5 public: 6 int nPublic; //公有成員 7 protected: 8 int nProtected; // 保護成員 9 }; 10 11 class Son : public Father 12 { 13 void AccessFather () 14 { 15 nPublic = 1; // ok; 16 nPrivate = 1; // wrong 17 nProtected = 1; // OK,訪問從基類繼承的protected成員 18 Son f; 19 f.nProtected = 1; //wrong ,f不是當前對象 20 } 21 }; 22 23 int main() 24 { 25 Father f; 26 Son s; 27 f.nPublic = 1; // Ok 28 s.nPublic = 1; // Ok 29 f.nProtected = 1; // error 30 f.nPrivate = 1; // error 31 s.nProtected = 1; //error 32 s.nPrivate = 1; // error 33 return 0; 34 }
派生類的構造函數
在創建派生類的對象時,需要調用基類的構造函數:初始化派生類對象中從基類繼承的成員。在執行一個派生類的構造函數之前,總是先執行基類的構造函數。
調用基類構造函數的兩種方式
(1)顯式方式:在派生類的構造函數中,為基類的構造函數提供參數.derived::derived(arg_derived-list):base(arg_base-list)
(2)隱式方式:在派生類的構造函數中,省略基類構造函數時,派生類的構造函數則自動調用基類的默認構造函數.
派生類的析構函數被執行時,執行完派生類的析構函數後,自動調用基類的析構函數。
在創建派生類的對象時:
(1)先執行基類的構造函數,用以初始化派生類對象中從基類繼承的成員;
(2)再執行成員對象類的構造函數,用以初始化派生類對象中成員對象。
(3)最後執行派生類自己的構造函數
在派生類對象消亡時:
(1)先執行派生類自己的析構函數
(2)再依次執行各成員對象類的析構函數
(3)最後執行基類的析構函數
析構函數的調用順序與構造函數的調用順序相反。
賦值規則
(1)派生類的對象可以賦值給基類對象
b = d;
(2)派生類對象可以初始化基類引用
base & br = d;
(3)派生類對象的地址可以賦值給基類指針
base * pb = & d;
如果派生方式是 private或protected,則上述三條不可行。
公有派生的情況下,派生類對象的指針可以直接賦值給基類指針
Base * ptrBase = &objDerived;
(1)ptrBase指向的是一個Derived類的對象;
*ptrBase可以看作一個Base類的對象,訪問它的public成員直接通過ptrBase即可,但不能通過ptrBase訪問objDerived對象中屬於Derived類而不屬於Base類的成員
(2)即便基類指針指向的是一個派生類的對象,也不能通過基類指針訪問基類沒有,而派生類中有的成員。
(3)通過強制指針類型轉換,可以把ptrBase轉換成Derived類的指針
Base * ptrBase = &objDerived;
Derived *ptrDerived = (Derived * ) ptrBase;
要保證ptrBase指向的是一個Derived類的對象,否則很容易會出錯。
新標準C++程序設計讀書筆記_繼承和多態