張宇
摘要:繼承是C++面向?qū)ο蟪绦蛟O(shè)計(jì)中的重要概念,也是類的特性之一。通過繼承可以循序漸進(jìn)的接近對(duì)象的本質(zhì),同時(shí)也在編程中提高了代碼的重用率,受到廣泛的運(yùn)用。筆者在教授C++程序設(shè)計(jì)的過程中,針對(duì)類的特性,繪制了類圖,并應(yīng)用類圖來(lái)講授類繼承的三種方式。有圖形的配合,形象生動(dòng),降低了學(xué)生的理解難度,收到學(xué)生的歡迎。
關(guān)鍵詞:類;類圖;繼承;對(duì)象;重用率
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)12-2781-05
1類圖的概念
類是一種用戶自定義的類型,它和基本類型,如浮點(diǎn)型、整型,有類似的特征。同樣,我們也可以聲明某個(gè)類類型的變量,這個(gè)變量就稱為類的對(duì)象,聲明對(duì)象的過程叫做類的實(shí)例化。類和基本類型的區(qū)別在于,類類型中同時(shí)包含了對(duì)數(shù)據(jù)進(jìn)行操作的函數(shù)。
類的成員可以有public(公有)、protected(保護(hù))和private(私有)三種訪問控制屬性,外界只能訪問類的公有成員。為了形象的描述類,筆者根據(jù)類封裝的特性在教學(xué)過程中設(shè)計(jì)了一個(gè)稱為“類圖”的圖形。如圖1所示。
圖1類內(nèi)部成員訪問示意圖
外框①表示類是數(shù)據(jù)成員和函數(shù)成員的封裝。箭頭②表示外界能訪問類的公有成員。方框③包含類的公有成員,表示類的外部接口。小箭頭④表示類的公有成員可以訪問類的保護(hù)和私有成員。方框⑤包含類私有和保護(hù)成員,表示類私有和保護(hù)成員外界不能直接訪問。
通過類圖我們可以很清楚的看到類成員的訪問權(quán)限。
2類的繼承和派生
面向?qū)ο蟮某绦蛟O(shè)計(jì)提供了類的繼承機(jī)制,該機(jī)制自動(dòng)地為一個(gè)類提供來(lái)自另一個(gè)類的操作和屬性,這使得程序員只需要在新類中添加已有類中沒有的成員來(lái)建立新類。以原有的類為基礎(chǔ)產(chǎn)生新的類,我們就說(shuō)新類繼承了原有的類,或者說(shuō)從原有類派生出新類。在這個(gè)過程中,原有的類我們稱為基類,新類我們稱為派生類(或稱為父類和子類)。
在C++中,聲明派生類的一般形式為:
class派生類名:繼承方式基類名1,繼承方式基類名2, ,繼承方式基類名n{
派生類的成員聲明;
};
在C++程序設(shè)計(jì)中,生成一個(gè)類的派生類,需要指定基類的類名,繼承方式和新增加的成員。繼承方式規(guī)定了派生類中從基類繼承的成員的訪問控制權(quán)限。繼承方式有公有繼承、保護(hù)繼承和私有繼承三種方式,其關(guān)鍵字分別為public、protected和private。派生類成員指除了從基類繼承來(lái)的所有成員之外,自己擴(kuò)充的數(shù)據(jù)和函數(shù)成員。
例如已經(jīng)聲明一個(gè)學(xué)生類Student,下面的語(yǔ)句聲明了一個(gè)從學(xué)生類派生而來(lái)的研究生類GraduateStudent:
class GraduateStudent : public Student
{
public:
GraduateStudent( );
~GraduateStudent( );}
;
派生類由基類除構(gòu)造函數(shù)和析構(gòu)函數(shù)以外的全部成員和派生類新增成員組成。那么基類成員在派生類中的訪問控制屬性如何呢?這個(gè)由派生時(shí)的繼承方式?jīng)Q定呢。
下面我們將討論不同繼承方式時(shí)派生類中基類成員的訪問控制屬性,并繪制派生類的“類圖”。
3繼承方式
在這里我們首先定義一個(gè)基類Point(點(diǎn))類。Point(點(diǎn))類有兩個(gè)數(shù)據(jù)成員:x坐標(biāo)和y坐標(biāo)。//Point.h
class Point
{
private:float x,y;
protected:float GetX2( ){return x*x;}
float GetY2( ){return y*y;}
public:void Start(float xx=0, float yy=0) {x=xx; y=yy;}
void Move(float xOf, float yOf) {x=y+xOf ; y=y+yOf;}
float GetX( ){return x;}
float GetY( ){return y;}
};
Point類用類圖表示如下:
圖2Point類圖
由Point類派生出新類Circle(圓)類。圓是由圓心和半徑構(gòu)成的,圓的圓心具備了Point類的全部特征,同時(shí)圓自身也有一些特點(diǎn),比如有半徑等。我們希望能夠訪問圓心的坐標(biāo),能夠獲得半徑的大小。
接下來(lái)我們討論對(duì)于三種繼承方式,Circle(圓)類分別需要怎樣如何設(shè)計(jì)才能達(dá)到上述要求,并畫出類圖。
1)公有繼承
當(dāng)類的繼承方式為公有繼承的時(shí)候,基類的public(公有)和protected(保護(hù))成員在派生類中訪問權(quán)限不變,而基類的private(私有)成員在派生類中不可直接訪問。
表1公有繼承在派生類中的訪問權(quán)限
公有繼承的派生類類圖如下所示:
圖3公有繼承的派生類類圖
[例1-1] Point類的公有繼承。
#include”Point.h”
class Circle :public Point//派生類聲明部分
private: float r;
public:void Start(float X, float Y, float R){Point::Start(X,Y); r=R;}
float GetR(){return r;}
};
這里派生類Circle繼承了基類Point,因此派生類Circle吸收了基類Point除默認(rèn)的構(gòu)造函數(shù)和默認(rèn)的析構(gòu)函數(shù)以外的所有成員。繼承方式為公有繼承,所以基類中的公有成員和保護(hù)成員在派生類中訪問屬性保持原樣,基類中的私有成員在派生類中不可直接訪問。
Circle類中繼承的獲得圓心坐標(biāo)的函數(shù)(GetX()和GetY())訪問控制屬性是公共的,所以只需添加獲得半徑的函數(shù)GetR()即可。
公有繼承后的Circle類用類圖表示如下:
圖4 Circle類圖
Circle類繼承了Point類的成員,實(shí)現(xiàn)了代碼的重用,同時(shí)通過添加新的成員,加入了自身的特性,實(shí)現(xiàn)了代碼的擴(kuò)充。公有繼承是類的繼承中用的最多的繼承方式。
2)私有繼承
當(dāng)類的繼承方式為私有繼承的時(shí)候,基類中的public(公有)和protected(保護(hù))成員被吸收后成為派生類的私有成員,而基類的private(私有)成員在派生類中不可直接訪問。
表2私有繼承在派生類中的訪問屬性
私有繼承的派生類類圖如下所示:
圖5私有繼承的派生類類圖
我們將例1-1中的繼承方式改為私有繼承。派生類Circle繼承了基類Point,因此派生類Circle吸收了基類Point除默認(rèn)構(gòu)造函數(shù)和默認(rèn)析構(gòu)函數(shù)以外的所有成員。繼承方式為私有繼承,所以基類中的公有成員和保護(hù)成員在在派生類中都變成了私有成員,基類原來(lái)的對(duì)外接口全部被隱藏,外部使用者不能通過派生類對(duì)象訪問基類原來(lái)的任何成員。派生類的新增成員可以訪問從基類繼承過來(lái)的公有成員和保護(hù)成員。
[例1-2] Point類的私有繼承。
經(jīng)過私有繼承以后,從基類繼承的成員都變成了派生類的私有成員或不可直接訪問的成員,如果進(jìn)一步派生的話,基類全部成員就無(wú)法在新的派生類中直接訪問。因此,私有繼承之后,基類的成員就無(wú)法在以后的派生類中直接發(fā)揮作用,相當(dāng)于終止了基類的功能,為了保證基類的原來(lái)的對(duì)外接口特征在派生類中也存在,常常在派生類中重新聲明同名的成員。
本例中,私有繼承后,基類的成員函數(shù)GetX()、GetY()和Move()均變成了派生類的私有函數(shù)成員,外界不能直接訪問。為了在派生類中仍能訪問圓心坐標(biāo),我們可以在Circle類中添加以上三個(gè)函數(shù)成員。則派生類的聲明可以改為:
#include”Point.h”
ClassCircle: private Point//派生類聲明部分
{
private:float r;
public:void Start(float X, float Y, float R){Point::Start(X,Y); r=R;}
float GetR(){return r;}
void Move(float xOf, float yOf){Point::Move(xOf,yOf);}
float GetX(){return Point::GetX();}
float GetY(){return Point::GetY();}
};
公有繼承后的Circle類用類圖表示如下:
圖6 Circle類圖
Circle類中繼承的獲得圓心坐標(biāo)的函數(shù)(GetX()和GetY())訪問控制屬性是私有的,派生類對(duì)象不能直接訪問,所以在新增成員除了需要添加獲得半徑的函數(shù)GetR(),還需要添加獲得圓心坐標(biāo)的函數(shù)(GetX()和GetY())。
3)保護(hù)繼承
當(dāng)類的繼承方式為保護(hù)繼承的時(shí)候,基類中的public(公有)和protected(保護(hù))成員被吸收后成為派生類的保護(hù)成員,而基類中的private(私有)成員在派生類中不可直接訪問。
表3保護(hù)繼承在派生類中的訪問屬性
保護(hù)繼承的派生類的類圖如下所示:
圖7保護(hù)繼承的派生類類圖
我們將例1-1中的繼承方式改為保護(hù)繼承。派生類Circle繼承了基類Point,因此派生類Circle吸收了基類Point除默認(rèn)構(gòu)造函數(shù)和默認(rèn)析構(gòu)函數(shù)以外的所有成員。繼承方式為保護(hù)繼承,所以基類中的公有成員和保護(hù)成員在在派生類中都變成了保護(hù)成員,基類原來(lái)的對(duì)外接口全部被隱藏,外部使用者不能通過派生類對(duì)象訪問基類原來(lái)的任何成員。派生類的新增成員可以訪問從基類繼承過來(lái)的公有成員和保護(hù)成員。
[例1-3] Point類的保護(hù)繼承。
經(jīng)過保護(hù)繼承以后,從基類繼承的成員都變成了派生類的保護(hù)成員或不可直接訪問的成員。因此,保護(hù)繼承之后,基類的成員就無(wú)法在以后的派生類中直接發(fā)揮作用,為了保證基類的原來(lái)的對(duì)外接口特征在派生類中也存在,常常在派生類中重新聲明同名的成員。
本例中,保護(hù)繼承后,基類的成員函數(shù)GetX()、GetY()和Move()均變成了派生類的保護(hù)函數(shù)成員,外界不能直接訪問。為了在派生類中仍能訪問圓心坐標(biāo),我們可以在Circle類中添加以上三個(gè)函數(shù)成員。則派生類的聲明可以改為:
#include”Point.h”
class Circle: protected Point
{
private:float r;
public:void Start(float X, float Y, float R){Point::Start(X,Y); r=R;}
float GetR(){return r;}
void Move(float xOf, float yOf){Point::Move(xOf,yOf);}
float GetX(){return Point::GetX();}
float GetY(){return Point::GetY();}
};
保護(hù)繼承后的Circle類用類圖表示如下:
圖8 Circle類圖
Circle類中繼承的獲得圓心坐標(biāo)的函數(shù)(GetX()和GetY())訪問控制屬性是保護(hù)的,派生類對(duì)象不能直接訪問,所以在新增成員除了需要添加獲得半徑的函數(shù)GetR(),還需要添加獲得圓心坐標(biāo)的函數(shù)(GetX()和GetY())。
4)私有繼承和保護(hù)繼承的區(qū)別
從類圖上看,類保護(hù)繼承和私有繼承似乎一樣:基類私有成員在派生類中不能直接訪問,基類的公有成員和保護(hù)成員可以被派生類新增成員訪問,外部使用者不能通過對(duì)象直接調(diào)用基類它們。但是,當(dāng)以派生類作為新的基類繼續(xù)派生的時(shí)候,二者的區(qū)別就出現(xiàn)了。
假設(shè)Point類分別以私有和保護(hù)兩種繼承方式派生出Circle類,再在Circle類的基礎(chǔ)上以公共繼承的方式派生出圓柱體類Cylin der。仔細(xì)分析兩種條件下的圓柱Cylinder類的成員,我們會(huì)發(fā)現(xiàn)Point類的公共成員在Cylinder類中訪問控制屬性不同。
//Cylinder.h
#include”Circle.h”
class Cylinder: public Circle
{
private:float h;
public:float GetH() {return h;}
};
參考文獻(xiàn):
[1]侯俊杰.深入淺出MFC[M].武漢:華中科技大學(xué)出版社,2003.
[2]錢能.C++程序設(shè)計(jì)教程[M].北京:清華大學(xué)出版社,1999.
[3]鄭莉,董淵.C++語(yǔ)言程序設(shè)計(jì)[M].北京:清華大學(xué)出版社,2001.
[4]薩師煊,王珊.數(shù)據(jù)庫(kù)系統(tǒng)概述[M].3版.北京:高等教育出版社,2002.
[5] Date C J.數(shù)據(jù)庫(kù)系統(tǒng)導(dǎo)論[M].7版.北京:機(jī)械工業(yè)出版社,2000,10.