c第4章類與對象_第1頁
c第4章類與對象_第2頁
c第4章類與對象_第3頁
c第4章類與對象_第4頁
c第4章類與對象_第5頁
已閱讀5頁,還剩61頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第四章類與對象目錄4.1面向對象程序設計的基本特點4.2類和對象4.3構造函數和析構函數4.4類的組合*4.5UML圖形標識4.6結構體和聯合體4.7綜合實例——個人銀行賬戶管理程序*4.8深度探索4.9小結2面向對象的方法目的:實現軟件設計的產業化。觀點:自然界是由實體(對象)所組成。程序設計方法:使用面向對象的觀點來描述模仿并處理現實問題。要求:高度概括、分類、和抽象。34.1面向對象程序設計的基本特點4.1.1抽象抽象是對具體對象(問題)進行概括,抽出這一類對象的公共性質并加以描述的過程。先注意問題的本質及描述,其次是實現過程或細節。數據抽象:描述某類對象的屬性或狀態(對象相互區別的物理量)。代碼抽象:描述某類對象的共有的行為特征或具有的功能。抽象的實現:通過類的聲明。44.1面向對象程序設計的基本特點抽象實例——鐘表數據抽象:int

hour,int

minute,int

second代碼抽象:setTime(),showTime()54.1面向對象程序設計的基本特點——4.1.1抽象抽象實例——鐘表(續)classClock{

public:voidsetTime(int

newH,int

newM,int

newS);

voidshowTime();

private:

inthour,minute,second;};64.1面向對象程序設計的基本特點——4.1.1抽象抽象實例——人數據抽象:stringname,stringgender,int

age,int

id代碼抽象:生物屬性角度:

getCloth(),eat(),step(),…社會屬性角度:

work(),promote(),…74.1面向對象程序設計的基本特點——4.1.1抽象4.1.2封裝將抽象出的數據成員、代碼成員相結合,將它們視為一個整體。目的是增強安全性和簡化編程,使用者不必了解具體的實現細節,而只需要通過外部接口,以特定的訪問權限,來使用類的成員。實現封裝:類聲明中的{}84.1面向對象程序設計的基本特點4.1.2封裝(續)實例:classClock{

public:void

setTime(int

newH,int

newM,int

newS);

voidshowTime();

private:inthour,minute,second;};94.1面向對象程序設計的基本特點邊界特定的訪問權限外部接口4.1.3繼承是C++中支持層次分類的一種機制,允許程序員在保持原有類特性的基礎上,進行更具體的說明。實現:聲明派生類——見第7章104.1面向對象程序設計的基本特點4.1.4多態多態:同一名稱,不同的功能實現方式。目的:達到行為標識統一,減少程序中標識符的個數。實現:重載函數和虛函數——見第8章114.1面向對象程序設計的基本特點4.2類和對象類是具有相同屬性和行為的一組對象的集合,它為屬于該類的全部對象提供了統一的抽象描述,其內部包括屬性和行為兩個主要部分。利用類可以實現數據的封裝、隱藏、繼承與派生。利用類易于編寫大型復雜程序,其模塊化程度比C中采用函數更高。124.2.1類的定義類是一種用戶自定義類型,聲明形式:class類名稱{

public:

公有成員(外部接口)

private:

私有成員

protected:

保護型成員}134.2類和對象4.2.2類成員的訪問控制

——公有類型成員在關鍵字public后面聲明,它們是類與外部的接口,任何外部函數都可以訪問公有類型數據和函數。144.2類和對象私有類型成員在關鍵字private后面聲明,只允許本類中的函數訪問,而類外部的任何函數都不能訪問。如果緊跟在類名稱的后面聲明私有成員,則關鍵字private可以省略。154.2類和對象——4.2.2類成員的訪問控制保護類型成員與private類似,其差別表現在繼承與派生時對派生類的影響不同,第七章講。164.2類和對象——4.2.2類成員的訪問控制4.2.3對象類的對象是該類的某一特定實體,即類類型的變量。聲明形式:

類名對象名;例:ClockmyClock;類中成員互訪直接使用成員名類外訪問使用“對象名.成員名”方式訪問

public屬性的成員174.2類和對象4.2.4類的成員函數在類中說明原型,可以在類外給出函數體實現,并在函數名前使用類名加以限定。也可以直接在類中給出函數體,形成內聯成員函數。允許聲明重載函數和帶默認形參值的函數184.2類和對象內聯成員函數為了提高運行時的效率,對于較簡單的函數可以聲明為內聯形式。內聯函數體中不要有復雜結構(如循環語句和switch語句)。在類中聲明內聯成員函數的方式:將函數體放在類的聲明中。使用inline關鍵字。194.2類和對象——4.2.4類的成員函數內聯成員函數舉例(一)classPoint{public:voidinit(int

initX,int

initY){x=initX;y=initY;}

int

getX(){returnx;}

int

getY(){returny;}private:

intx,y;};204.2類和對象——4.2.4類的成員函數內聯成員函數舉例(二)classPoint{public:voidinit(int

initX,int

initY);

int

getX();

int

getY();

private:

intx,y;};214.2類和對象——4.2.4類的成員函數內聯成員函數舉例(三)inlinevoidPoint::

init(int

initX,int

initY){x=initX;y=initY;}inlineint

Point::getX(){returnx;}inlineint

Point::GetY(){returny;}224.2類和對象——4.2.4類的成員函數4.2.5程序實例——例4-1#include<iostream>usingnamespacestd;classClock{......//類的聲明略}//......類的實現略intmain(){ ClockmyClock; myClock.setTime(8,30,30);

myClock.showTime(); return0;}234.2類和對象類的成員(續)voidClock::setTime(int

newH,int

newM,

int

newS){hour=newH;minute=newM;second=newS;}voidClock::showTime(){

cout<<hour<<":"<<minute<<":"<<second;}244.2類和對象——4.2.2類成員的訪問控制4.3.1構造函數構造函數的作用是在對象被創建時使用特定的值構造對象,或者說將對象初始化為一個特定的狀態。在對象創建時由系統自動調用。如果程序中未聲明,則系統自動產生出一個隱含的參數列表為空的構造函數允許為內聯函數、重載函數、帶默認形參值的函數254.3構造函數和析構函數構造函數舉例classClock{public:

Clock(int

newH,int

newM,int

newS);//構造函數

voidsetTime(int

newH,int

newM,int

newS); voidshowTime();private:

inthour,minute,second;};264.3構造函數和析構函數——4.3.1構造函數構造函數舉例(續)//構造函數的實現:Clock::Clock(int

newH,int

newM,int

newS){ hour=newH; minute=newM; second=newS;}intmain(){

Clockc(0,0,0);//隱含調用構造函數,將初始值作為實參。

c.showTime(); return0;}274.3構造函數和析構函數——4.3.1構造函數構造函數舉例--考慮對象有無初始化的要求(方案1)classClock{public:

Clock(int

newH=0,intnewM=0,intnewS=0);//構造函數

voidsetTime(int

newH,int

newM,int

newS); voidshowTime();private:

inthour,minute,second;};28//構造函數的實現:Clock::Clock(int

newH,int

newM,int

newS){ hour=newH; minute=newM; second=newS;}intmain(){

Clockc1(10,0,0),c2;

c1.showTime();c2.setTime(8,30,30);c2.showTime(); return0;}29構造函數舉例--考慮對象有無初始化的要求(方案2)classClock{public:

Clock(int

newH,int

newM,int

newS);//自定義構造函數Clock();//默認構造函數

voidsetTime(int

newH,int

newM,int

newS); voidshowTime();private:

inthour,minute,second;};30//自定義構造函數的實現:Clock::Clock(int

newH,int

newM,int

newS){ hour=newH; minute=newM; second=newS;}//默認構造函數的實現:Clock::Clock(){ hour=0; minute=0; second=0;}31intmain(){

Clockc1(10,0,0),c2;

c1.showTime();c2.setTime(8,30,30);c2.showTime(); return0;}324.3.2拷貝構造函數拷貝構造函數是一種特殊的構造函數,其形參為本類的對象引用。class類名{public:

類名(形參);//構造函數類名(類名&對象名);//拷貝構造函數

...};類名::類(類名&對象名)//拷貝構造函數的實現{函數體}334.3構造函數和析構函數例4-2Point類的完整程序classPoint{//Point類的定義public:

Point(intxx=0,int

yy=0){x=xx;y=yy;}

//構造函數

Point(Point&p);//拷貝構造函數

int

getX(){returnx;}

int

getY(){returny;}private:

intx,y;//私有數據};//成員函數的實現Point::Point(Point&p){x=p.x;y=p.y;

cout<<"Callingthecopyconstructor"<<endl;}344.3構造函數和析構函數——4.3.2拷貝構造函數//形參為Point類對象的函數voidfun1(Pointp){

cout<<p.getX()<<endl;}//返回值為Point類對象的函數Pointfun2(){ Pointa(1,2); returna;}

//主程序intmain(){ Pointa(4,5); //第一個對象A Pointb=a; //情況一,用A初始化B。第一次調用拷貝構造函數

cout<<b.getX()<<endl; fun1(b); //情況二,對象B作為fun1的實參。第二次調用拷貝構造函數

b=fun2(); //情況三,函數的返回值是類對象,函數返回時調用拷貝構造函數

cout<<b.getX()<<endl; return0;}354.3構造函數和析構函數——4.3.2拷貝構造函數例4-2(續)隱含的拷貝構造函數如果程序員沒有為類聲明拷貝初始化構造函數,則編譯器自己生成一個隱含的拷貝構造函數。這個構造函數執行的功能是:用作為初始值的對象的每個數據成員的值,初始化將要建立的對象的對應數據成員。364.3構造函數和析構函數——4.3.2拷貝構造函數4.3.3析構函數完成對象被刪除前的一些清理工作。在對象的生存期結束的時刻系統自動調用它,然后再釋放此對象所屬的空間。如果程序中未聲明析構函數,編譯器將自動產生一個隱含的析構函數。374.3構造函數和析構函數構造函數和析構函數舉例#include<iostream>usingnamespacestd;classPoint{public:

Point(int

xx,int

yy);~Point();//...其他函數原型private:

intx,y;};384.3構造函數和析構函數——4.3.3析構函數Point::Point(int

xx,int

yy){x=xx;y=yy;}Point::~Point(){}//...其他函數的實現略4.3.4程序實例——例4-3一圓形游泳池如圖所示,現在需在其周圍建一圓形過道,并在其四周圍上柵欄。柵欄價格為35元/米,過道造價為20元/平方米。過道寬度為3米,游泳池半徑由鍵盤輸入。要求編程計算并輸出過道和柵欄的造價。39游泳池過道4.3構造函數和析構函數#include<iostream>usingnamespacestd;constfloatPI=3.141593; //給出p的值constfloatFENCE_PRICE=35; //柵欄的單價constfloatCONCRETE_PRICE=20;//過道水泥單價classCircle{ //聲明定義類Circle及其數據和方法public: //外部接口

Circle(floatr); //構造函數

floatcircumference(); //計算圓的周長

floatarea(); //計算圓的面積private: //私有數據成員

floatradius; //圓半徑};//類的實現//構造函數初始化數據成員radiusCircle::Circle(floatr){ radius=r;} 404.3構造函數和析構函數——4.3.4程序實例例4-3(續)floatCircle::circumference(){//計算圓的周長return2*PI*radius;}floatCircle::area(){//計算圓的面積returnPI*radius*radius;}intmain(){ floatradius;

cout<<"Entertheradiusofthepool:";//提示用戶輸入半徑

cin>>radius; Circlepool(radius); //游泳池邊界

CirclepoolRim(radius+3); //柵欄

//計算柵欄造價并輸出

floatfenceCost=poolRim.circumference()*FENCE_PRICE;

cout<<"FencingCostis$"<<fenceCost<<endl;414.3構造函數和析構函數——4.3.4程序實例例4-3(續)//計算過道造價并輸出

floatconcreteCost=(poolRim.area()-pool.area())*CONCRETE_PRICE;

cout<<"ConcreteCostis$"<<concreteCost<<endl; return0;}運行結果:

Entertheradiusofthepool:10FencingCostis$2858.85ConcreteCostis$4335.4424.3構造函數和析構函數——4.3.4程序實例例4-3(續)4.4.1組合類中的成員數據是另一個類的對象。可以在已有抽象的基礎上實現更復雜的抽象。434.4類的組合類組合的構造函數設計原則:不僅要負責對本類中的基本類型成員數據賦初值,也要對對象成員初始化。聲明形式:類名::類名(對象成員所需的形參,本類成員形參):對象1(參數),對象2(參數),......{本類初始化}444.4類的組合——4.4.1組合類組合的構造函數調用構造函數調用順序:先調用內嵌對象的構造函數(按內嵌時的聲明順序,先聲明者先構造)。然后調用本類的構造函數。(析構函數的調用順序相反)初始化列表中未出現的內嵌對象,用默認構造函數(即無形參的)初始化系統自動生成的隱含的默認構造函數中,內嵌對象全部用默認構造函數初始化454.4類的組合——4.4.1組合例4-4類的組合,線段(Line)類//4_4.cpp#include<iostream>#include<cmath>usingnamespacestd;classPoint{ //Point類定義public:

Point(intxx=0,int

yy=0){ x=xx; y=yy; }

Point(Point&p);

int

getX(){returnx;}

int

getY(){returny;}private:

intx,y;};Point::Point(Point&p){ //拷貝構造函數的實現

x=p.x; y=p.y;

cout<<"CallingthecopyconstructorofPoint"<<endl;}464.4類的組合——4.4.1組合//類的組合classLine{ //Line類的定義public: //外部接口

Line(Pointxp1,Pointxp2);

Line(Line&l); doublegetLen(){returnlen;}private: //私有數據成員

Pointp1,p2; //Point類的對象p1,p2 doublelen;};//組合類的構造函數Line::Line(Pointxp1,Pointxp2):p1(xp1),p2(xp2){

cout<<"CallingconstructorofLine"<<endl; doublex=double(p1.getX()-p2.getX()); doubley=double(p1.getY()-p2.getY());

len=sqrt(x*x+y*y);}Line::Line(Line&l):p1(l.p1),p2(l.p2){//組合類的拷貝構造函數

cout<<"CallingthecopyconstructorofLine"<<endl;

len=l.len;}474.4類的組合——4.4.1組合例4-4(續)//主函數intmain(){ Pointmyp1(1,1),myp2(4,5); //建立Point類的對象

Lineline1(myp1,myp2); //建立Line類的對象

Lineline2(line1); //利用拷貝構造函數建立一個新對象

cout<<"Thelengthoftheline1is:";

cout<<line1.getLen()<<endl;

cout<<"Thelengthoftheline2is:";

cout<<line2.getLen()<<endl; return0;}484.4類的組合——4.4.1組合例4-4(續)運行結果如下:CallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingconstructorofLineCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofLineThelengthofthelineis:5Thelengthoftheline2is:54.4.2前向引用聲明類應該先聲明,后使用如果需要在某個類的聲明之前,引用該類,則應進行前向引用聲明。前向引用聲明只為程序引入一個標識符,但具體聲明在其他地方。494.4類的組合舉例classB;//前向引用聲明classA{public:voidf(Bb);};classB{public:voidg(Aa);};504.4類的組合——4.4.2前向引用聲明前向引用聲明注意事項使用前向引用聲明雖然可以解決一些問題,但它并不是萬能的。需要注意的是,盡管使用了前向引用聲明,但是在提供一個完整的類聲明之前,不能聲明該類的對象,也不能在內聯成員函數中使用該類的對象。請看下面的程序段:514.4類的組合——4.4.2前向引用聲明classFred;//前向引用聲明classBarney{Fredx;//錯誤:類Fred的聲明尚不完善};classFred{Barneyy;};classFred; //前向引用聲明

classBarney{public:……voidmethod(){

x.yabbaDabbaDo(); //錯誤:Fred類的對象在定義之前被使用

}private:Fred&x;//正確,經過前向引用聲明,可以聲明Fred類的對象引用};

classFred{public:voidyabbaDabbaDo();private:Barney&y;};前向引用聲明注意事項(續)524.4類的組合——4.4.2前向引用聲明前向引用聲明注意事項(續)應該記住:當你使用前向引用聲明時,你只能使用被聲明的符號,而不能涉及類的任何細節。534.4類的組合——4.4.2前向引用聲明4.6.1結構體結構體是一種特殊形態的類與類的唯一區別:類的缺省訪問權限是private,結構體的缺省訪問權限是public結構體存在的主要原因:與C語言保持兼容什么時候用結構體而不用類定義主要用來保存數據、而沒有什么操作的類型人們習慣將結構體的數據成員設為公有,因此這時用結構體更方便544.6結構體和聯合體結構體的定義和初始化結構體定義struct

結構體名稱{

公有成員protected:

保護型成員private:

私有成員};一些結構體變量的初始化可以用以下形式類型名變量名

={成員數據1初值,成員數據2初值,……};554.6結構體和聯合體——4.6.1結構體例4-7用結構體表示學生的基本信息#include<iostream>#include<iomanip>#include<string>usingnamespacestd;structStudent{ //學生信息結構體

intnum; //學號

stringname; //姓名,字符串對象,將在第6章詳細介紹

charsex; //性別

intage; //年齡};564.6結構體和聯合體——4.6.1結構體例4-7(續)intmain(){ Studentstu={97001,"LinLin",'F',19};

cout<<"Num:"<<stu.num<<endl;

cout<<"Name:"<<<<endl;

cout<<"Sex:"<<stu.sex<<endl;

cout<<"Age:"<<stu.age<<endl; return0;}運行結果:Num:97001Name:LinLinSex:FAge:19574.6結構體和聯合體——4.6.1結構體4.6.2聯合體聲明形式union聯合體名稱{公有成員protected:

保護型成員private:

私有成員};特點:成員共用相同的內存單元任何兩個成員不會同時有效584.6結構體和聯合體聯合體的內存分配unionMark{ //表示成績的聯合體 chargrade; //等級制的成績

boolpass; //只記是否通過課程的成績

intpercent; //百分制的成績};594.6結構體和聯合體——4.6.2聯合體Markgradepercentpass無名聯合例:union{

inti;floatf;}在程序中可以這樣使用:i=10;f=2.2;604.6結構體和聯合體——4.6.2聯合體無名聯合沒有標記名,只是聲明一個成員項的集合,這些成員項具有相同的內存地址,可以由成員項的名字直接訪問。例4-8使用聯合體保存成績信息,并且輸出。#include<string>#include<iostream>usingnamespacestd;classExamInfo{private: stringname; //課程名稱

enum{GRADE,PASS,PERCENTAGE}mode;//采用何種計分方式

union{ chargrade; //等級制的成績

boolpass; //只記是否通過課程的成績

intpercent; //百分制的成績

};614.6結構體和聯合體——4.6.2聯合體例4-8(續)public:

//三種構造函數,分別用等級、是否通過和百分初始化

ExamInfo(stringname,chargrade) :name(name),mode(GRADE),grade(grade){}

ExamInfo(stringname,boolpass) :name(name),mode(PASS),pass(pass){}

ExamInfo(stringname,intpercent) :name(name),mode(PERCENTAGE),percent(percent){} voidshow();}624.6結構體和聯合體——4.6.2聯合體例4-8(續)voidExamInfo::show(){

cout<<name<<":"; switch(mode){ caseGRADE:cout<<grade;break; casePASS:cout<<(pass?"PASS":"FAIL");break; casePERCENTAGE:cout<<percent;break; }

cout<<endl;}634.6結構體和聯合體——4.6.2聯合體例4-8(續)intmain(){

ExamInfocourse1("English",'B');

ExamInfocourse2("Calculus",true);

ExamInfocourse3("C++Programming",85); course1.show(); course2.show(); course3.show(); return0;}運行結果:English:BCalculus:PASSC++Programming:85644.6結構體和聯合體——4.6.2聯合體4.7綜合實例——個人銀行賬戶管理程序我們以一個面向個人的銀行賬戶管理程序為例,說明類及成員函數的設計。例4-9:一個人可以有多個活期儲蓄賬戶,一個活期儲蓄賬戶包括賬號(id)、余額(balance)、年利率(rate)等信息,還包括顯示賬戶信息(show)、存款(deposit)、取款(withdraw)、結算利息(settle)等操作,654.7.1類的設計664.7綜合實例——個人銀行賬戶管理程序SavingsAccount- id:int- balance:double- rate:double- lastDate:int- accumulation:double- record(date:int,amount:double)- accumulate(date:int):double+SavingsAccount(date:int,id:int,rate:double)+getId():int+getBalance():double+getRate():double+show()+deposit(date:int,amount:double)+withdraw(date:int,amount:double)+settle(date:int)4.7.2源程序及說明——例4-9//4_9.cpp#include<iostream>#include<cmath>usingnamespacestd;classSavingsAccount{//儲蓄賬戶類private:

intid; //賬號

doublebalance; //余額

doublerate; //存款的年利率

int

lastDate; //上次變更余額的時期

doubleaccumulation; //余額按日累加之和

//記錄一筆帳,date為日期,amount為金額,desc為說明

voidrecord(intdate,doubleamount); //獲得到指定日期為止的存款金額按日累積值

doubleaccumulate(intdate)const{ returnaccumulation+balance*(date-lastDate); }674.7綜合實例——個人銀行賬戶管理程序public: //構造函數

SavingsAccount(intdate,intid,doublerate);

int

getId(){returnid;} doublegetBalance(){returnbalance;} doublegetRate(){returnrate;} voiddeposit(intdate,doubleamount); //存入現金

voidwithdraw(intdate,doubleamount); //取出現金

//結算利息,每年1月1日調用一次該函數

voidsettle(intdate);

voidshow();//顯示賬戶信息};//SavingsAccount類相關成員函數的實現SavingsAccount::SavingsAccount(intdate,intid,doublerate) :id(id),balance(0),rate(rate),lastDate(date),accumulation(0){

cout<<date<<"\t#"<<id<<"is

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論