按一下以編輯母片標題樣式,按一下以編輯母片文字樣式,第二層,第三層,第四層,第五層,*,Derived Class,前言,衍生類別的定義,單一繼承,public,protected,和 privated 基底類別,virtual 成員函式,RTTI(Run-time Type Information),Derived Class前言,1,前言,C+提供類別繼承的機制來擴充或更改現有類別的功能。我們可以利用此機制來達到以下兩個目的:,程式碼的再利用(code reuse),物件導向的設計(object-oriented design),前言C+提供類別繼承的機制來擴充或更改現有類別的功能。我,2,假定 B 是一個類別。我們可以用底下的格式來定義一個 B 的衍生類別 D:,class D :public B,/members of D,;,我們稱:D 繼承 B、B 是 D 的 base class(基底類別)或 superclass(,父類別)、以及 D 是 B 的 derived class(衍生類別)或 subclass(子類別)。,衍生類別的定義,class B,class D,類別繼承的圖示,假定 B 是一個類別。我們可以用底下的格式來定義一個 B 的,3,類別繼承通常是用來表達 kind-of,關係(或稱 is-a 關係):衍生類別是基底類別的一種。譬如:Manager(經理)也是 Employee(員工),所以我們先規劃好 Employee 類別,然後把 Manager 定義成 Employee 的一個衍生類別:,class Employee,/other members,private:,string first_name,family_name;,char middle_initial;,Date hiring_date;,short department;,;,class Manager:public Employee,/other members,private:,set group;,short level;,;,類別繼承通常是用來表達 kind-of 關係(或稱 is-a,4,Manager,的資料成員:,string first_name,family_name;,char middle_initial;,Date hiring_date;,short department;,set group;,short level;,衍生類別除了本身的資料成員以外,也具有基底類別的資料成員。譬如:,Employee,的資料成員:,string first_name,family_name;,char middle_initial;,Date hiring_date;,short department;,Manager 的資料成員:衍生類別除了本身的資料成員以外,,5,由於衍生類別是基底類別的子類別,因此衍生類別的物件可視為基底類別的物件;基底類別型態的指標也可用於衍生類別的物件,而不須要經過型態轉換。但反過來就不成立了。譬如:,void foo(Manager mm,Employee ee),Employee*pe=/ok,Manager*pm=/error,pe-level=2;/error:Employee doesnt have,/data member:level,pm=static_cast(pe);/ok:explicit type casting,pm-level=2;/ok:since pe points to a,/Manager object,由於衍生類別是基底類別的子類別,因此衍生類別的物件可視為基底,6,衍生類別及其朋友(friends)可以直接使用基底類別的 public,或 protected 成員,但是不能使用基底類別的 private 成員。譬如:,class B,public:,void f();,protected:,void g();,int _x;,private:,void h();,int _y;,;,class D:public B,friend void k(D);,void a()f();/ok,void b()g();/ok,void c()_x=0;/ok,void d()h();/error,void e()_y=0;/error,;,void k(D obj),obj.g();/ok,obj.f();/ok,obj._x=0;/ok,obj._y=0;/error,衍生類別及其朋友(friends)可以直接使用基底類別的 p,7,存取控制,本身與其朋友 衍生類別與其朋友外界,public,protected,private,x,x,x,我們用下表來總結類別成員的存取控制:,存取控制 本身與其朋友 衍生類別與其朋友,8,如果基底類別的成員函式不符合所需的話,我們可以在衍生類別中重新改寫(override)。譬如:,class Employee,public:,void print();,/other members,;,void Employee:print(),cout first_name ,middle_initial ,family_name;,class Manager:public Employee,public:,void print();,/other members,;,void Manager:print(),Employee:print();,cout level;,這項改寫的機制讓 code reuse 可以很容易地達成。,如果基底類別的成員函式不符合所需的話,我們可以在衍生類別中重,9,衍生類別的建構函式必須呼叫基底類別的建構函式(如果它存在的話),而且前者的參數必須包含後者的參數。譬如:,class Employee,public:,Employee(const string&n,int d),:family_name(n),department(d),/other members,;,class Manager:public Employee,public:,Manager(const string&n,int d,int lvl),:Employee(n,d),level(lvl),/other members,;,衍生類別的建構函式必須呼叫基底類別的建構函式(如果它存在的話,10,衍生類別的物件建構順序如下:,1.執行基底類別的建構函式。,2.執行衍生類別資料成員的建構函式。,3.執行衍生類別的建構函式。,衍生類別的物件解構順序則恰恰相反,即:,1.執行衍生類別的解構函式。,2.執行衍生類別資料成員的解構函式。,3.執行基底類別的解構函式。,資料成員和基底類別是按照宣告的順序來建構,解構則按照相反的順序。,衍生類別的物件建構順序如下:衍生類別的物件解構順序則恰恰相反,11,拷貝衍生類別物件至基底類別物件時,只拷貝基底類別的資料成員。,class Employee,Employee(const Employee,Employee,/,;,void f(const Manager&m),Employee e=m;/construct e from Employee part of m,e=m;/assign Employee part of m to e,拷貝衍生類別物件至基底類別物件時,只拷貝基底類別的資料成員。,12,範,例,class CPoint2D,public:,CPoint2D(int x=0,int y=0):_x(x),_y(y),int x()return _x;,int y()return _y;,void setX(int x)_x=x;,void setY(int y)_y=y;,void set(int x,int y)_x=x;_y=y;,bool isZero()return _x=0 ,double distance()return sqrt(_x*_x+_y*_y);,protected:,int _x,_y;,;,我們利用 CPoint2D,類別來定義 CPoint3D 類別。首先我們把 CPoint2D 的 private 成員改成 protected 成員,讓 CPoint3D 可以使用它們。,範class CPoint2D 我們利用 CPoint2D,13,class CPoint3D:public CPoint2D,public:,CPoint3D(int x=0,int y=0,int _z=0),:CPoint2D(x,y),_z(z),int z()return _z;,void setZ(int z)_z=x;,void set(int x,int y,int z)set(x,y);setZ(z);,bool isZero()return _x=0 ,double distance()return sqrt(_x*_x+_y*_y+_z*_z);,private:,int _z;,;,CPoint3D,改寫(override)CPoint2D 的 isZero()和 distance()函式。,class CPoint3D:public CPoint,14,#include,using namespace std;,#include“CPoint3D.h”,ostream&operator(ostream&os,CPoint3D p),os (p.x()“,“p.y()“,“p.z();,return os;,我們可以為 CPoint3D,類別定義輸出運算子 如下:,#include 我們可以為 CPoin,15,測試程式,#include“CPoint3D.h”,int main(),CPoint3D p(1,2,3);,cout p endl;,CPoint2D q(5,6);,q=p;,cout q endl;,p=q;/error,輸出結果,(1,2,3),(1,2),測試程式#include“CPoint3D.h”輸出結果,16,範,例,typedef unsigned short big5char;,class big5string:public string,public:,bool is_big5char(int idx);,big5char next_char(int idx);,int big5_length();,private:,bool in(char c,int min,int max)return min=0,char*cp=c_str();,if(cpidx 128|idx=length()-1),return false;,if(is_big5hiByte(cpidx)&is_big5loByte(cpidx+1),return true;,else,return false;,bool big5string:is_big5char(,18,big5char big5string:next_char(int idx),char*cp=c_str();,return is_big5char(idx)?cpidx*256+cpidx:cpidx;,int big5string:big5_length(),int len=0,k=0;,while(k length(),k=is_big5char(k)?k+2:k+1;,len+;,return len;,big5char big5string:next_char,19,測試程式,#include,#include,#include“big5string.h”,int main(),string s1(“Hi,“);,big5string s2;,s2=s1+“,好久不見”;,cout s2 endl;,cout “#of characters is:“s2.big5_length(