第4章C++類與對象_第1頁
第4章C++類與對象_第2頁
第4章C++類與對象_第3頁
第4章C++類與對象_第4頁
第4章C++類與對象_第5頁
已閱讀5頁,還剩82頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第4章C++類與對象第一頁,共87頁。4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點4.2類和對象4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)4.4類的組合4.5UML圖形標(biāo)識4.6結(jié)構(gòu)體和聯(lián)合體目錄2第二頁,共87頁。抽象是對具體對象(問題)進(jìn)行概括,抽出這一類對象的公共性質(zhì)并加以描述的過程。先注意問題的本質(zhì)及描述,其次是實現(xiàn)過程或細(xì)節(jié)。數(shù)據(jù)抽象:描述某類對象的屬性或狀態(tài)(對象相互區(qū)別的物理量)。代碼抽象:描述某類對象的共有的行為特征或具有的功能。抽象的實現(xiàn):通過類的聲明。4.1.1抽象4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點3第三頁,共87頁。數(shù)據(jù)抽象:inthour,intminute,intsecond代碼抽象:setTime(),showTime()抽象實例——鐘表4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點——4.1.1抽象4第四頁,共87頁。classClock{

public:voidsetTime(intnewH,intnewM,intnewS);

voidshowTime();

private:inthour,minute,second;};抽象實例——鐘表(續(xù))4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點——4.1.1抽象5第五頁,共87頁。將抽象出的數(shù)據(jù)成員、代碼成員相結(jié)合,將它們視為一個整體。目的是增強(qiáng)安全性和簡化編程,使用者不必了解具體的實現(xiàn)細(xì)節(jié),而只需要通過外部接口,以特定的訪問權(quán)限,來使用類的成員。實現(xiàn)封裝:類聲明中的{}4.1.2封裝4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點6第六頁,共87頁。實例:classClock{

public:voidsetTime(intnewH,intnewM,intnewS);

voidshowTime();

private:inthour,minute,second;};4.1.2封裝(續(xù))4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點邊界特定的訪問權(quán)限外部接口7第七頁,共87頁。是C++中支持層次分類的一種機(jī)制,允許程序員在保持原有類特性的基礎(chǔ)上,進(jìn)行更具體的說明。實現(xiàn):聲明派生類——見第7章4.1.3繼承4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點8第八頁,共87頁。多態(tài):同一名稱,不同的功能實現(xiàn)方式。目的:達(dá)到行為標(biāo)識統(tǒng)一,減少程序中標(biāo)識符的個數(shù)。強(qiáng)制多態(tài)、重載多態(tài)、包含多態(tài)、類型參數(shù)化多態(tài)實現(xiàn):數(shù)據(jù)類型轉(zhuǎn)換;函數(shù)和運算符重載;虛函數(shù)(第8章);模板(第9章)4.1.4多態(tài)4.1面向?qū)ο蟪绦蛟O(shè)計的基本特點9第九頁,共87頁。類是具有相同屬性和行為的一組對象的集合,它為屬于該類的全部對象提供了統(tǒng)一的抽象描述,其內(nèi)部包括屬性和行為兩個主要部分。利用類可以實現(xiàn)數(shù)據(jù)的封裝、隱藏、繼承與派生。利用類易于編寫大型復(fù)雜程序,其模塊化程度比C中采用函數(shù)更高。4.2類和對象10第十頁,共87頁。定義一個新的class也就定義了一個新的類型此類型的“合法值”是什么?構(gòu)造函數(shù)以及setXX函數(shù)需要進(jìn)行值的合法性檢查此類型應(yīng)該有什么樣的函數(shù)和操作符成員函數(shù)特殊的成員函數(shù):運算符重載函數(shù)(第8章)新類型的對象該如何被創(chuàng)建和銷毀?構(gòu)造和析構(gòu)函數(shù)內(nèi)存分配和釋放函數(shù)(operatornew、operatornew[]、operatordelete、operatordelete[])(第6、8章)*設(shè)計class就是設(shè)計類型4.2類和對象11第十一頁,共87頁。對象的初始化和賦值有何差別?復(fù)制構(gòu)造賦值(第8章)對象作為函數(shù)的參數(shù)如何以值傳遞?通過復(fù)制構(gòu)造函數(shù)實現(xiàn)傳值誰將使用此類型的對象成員?哪些是公有、私有、保護(hù)哪些函數(shù)和類應(yīng)該是友元(第5章)哪些函數(shù)應(yīng)該禁用?例如在一些特定設(shè)計中不允許默認(rèn)構(gòu)造函數(shù)被調(diào)用*設(shè)計class就是設(shè)計類型(續(xù))4.2類和對象12第十二頁,共87頁。類是一種用戶自定義類型,聲明形式:class類名稱{

public:

公有成員(外部接口)

private:

私有成員

protected:

保護(hù)型成員}4.2.1類的定義4.2類和對象13第十三頁,共87頁。在關(guān)鍵字public后面聲明,它們是類與外部的接口,任何外部函數(shù)都可以訪問公有類型數(shù)據(jù)和函數(shù)。4.2.2類成員的訪問控制

——公有類型成員4.2類和對象14第十四頁,共87頁。在關(guān)鍵字private后面聲明,只允許本類中的函數(shù)訪問,而類外部的任何函數(shù)都不能訪問。如果緊跟在類名稱的后面聲明私有成員,則關(guān)鍵字private可以省略。私有類型成員4.2類和對象——4.2.2類成員的訪問控制15第十五頁,共87頁。與private類似,其差別表現(xiàn)在繼承與派生時對派生類的影響不同,第七章講。保護(hù)類型成員4.2類和對象——4.2.2類成員的訪問控制16第十六頁,共87頁。類的對象是該類的某一特定實體,即類類型的變量。聲明形式:

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

public屬性的成員4.2.3對象4.2類和對象17第十七頁,共87頁。在類中說明原型,可以在類外給出函數(shù)體實現(xiàn),并在函數(shù)名前使用類名加以限定。也可以直接在類中給出函數(shù)體,形成內(nèi)聯(lián)成員函數(shù)。允許聲明重載函數(shù)和帶默認(rèn)形參值的函數(shù)4.2.4類的成員函數(shù)4.2類和對象18第十八頁,共87頁。為了提高運行時的效率,對于較簡單的函數(shù)可以聲明為內(nèi)聯(lián)形式。內(nèi)聯(lián)函數(shù)體中不要有復(fù)雜結(jié)構(gòu)(如循環(huán)語句和switch語句)。在類中聲明內(nèi)聯(lián)成員函數(shù)的方式:將函數(shù)體放在類的聲明中。使用inline關(guān)鍵字。內(nèi)聯(lián)成員函數(shù)4.2類和對象——4.2.4類的成員函數(shù)19第十九頁,共87頁。#include<iostream>usingnamespacestd;classClock{public:

voidsetTime(intnewH=0,intnewM=0,intnewS=0); voidshowTime();private:

inthour,minute,second;}intmain(){ ClockmyClock; myClock.setTime(8,30,30); myClock.showTime(); return0;}4.2.5程序?qū)嵗?-14.2類和對象運行結(jié)果:8:30:3020第二十頁,共87頁。voidClock::setTime(intnewH,intnewM, intnewS){hour=newH;minute=newM;second=newS;}voidClock::showTime(){cout<<hour<<":"<<minute<<":"<<second;}例4-1(續(xù))——類的實現(xiàn)4.2類和對象——4.2.2類成員的訪問控制21第二十一頁,共87頁。構(gòu)造函數(shù)的作用是在對象被創(chuàng)建時使用特定的值構(gòu)造對象,將對象初始化為一個特定的初始狀態(tài)。在對象創(chuàng)建時被自動調(diào)用如果程序中未聲明,則系統(tǒng)自動產(chǎn)生出一個默認(rèn)的構(gòu)造函數(shù),其參數(shù)列表為空構(gòu)造函數(shù)可以是內(nèi)聯(lián)函數(shù)、重載函數(shù)、帶默認(rèn)參數(shù)值的函數(shù)構(gòu)造函數(shù)名與類名相同,且沒有返回值;通常為公有函數(shù)。4.3.1構(gòu)造函數(shù)4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)22第二十二頁,共87頁。classClock{public:

Clock(intnewH,intnewM,intnewS);//構(gòu)造函數(shù)

voidsetTime(intnewH,intnewM,intnewS); voidshowTime();private: inthour,minute,second;};構(gòu)造函數(shù)舉例4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.1構(gòu)造函數(shù)23第二十三頁,共87頁。構(gòu)造函數(shù)的實現(xiàn):Clock::Clock(intnewH,intnewM,intnewS){hour=newH;minute=newM;second=newS;}建立對象時構(gòu)造函數(shù)的作用:intmain(){

Clockc(0,0,0);//此處將自動調(diào)用構(gòu)造函數(shù)

c.showTime(); return0;}構(gòu)造函數(shù)舉例(續(xù))4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.1構(gòu)造函數(shù)24第二十四頁,共87頁。調(diào)用時可以不需要參數(shù)的構(gòu)造函數(shù)都是默認(rèn)構(gòu)造函數(shù)。當(dāng)不定義構(gòu)造函數(shù)時,編譯器自動產(chǎn)生默認(rèn)構(gòu)造函數(shù)在類中可以自定義無參數(shù)的構(gòu)造函數(shù),也是默認(rèn)構(gòu)造函數(shù)全部參數(shù)都有默認(rèn)形參值的構(gòu)造函數(shù)也是默認(rèn)構(gòu)造函數(shù)下面兩個都是默認(rèn)構(gòu)造函數(shù),如果在類中同時出現(xiàn),將產(chǎn)生編譯錯誤:Clock();Clock(intnewH=0,intnewM=0,intnewS=0);*默認(rèn)構(gòu)造函數(shù)25第二十五頁,共87頁。復(fù)制構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),其形參為本類的對象引用。作用是用一個已存在的對象去初始化同類型的新對象。class類名{public:

類名(形參);//構(gòu)造函數(shù)類名(const類名&對象名);//復(fù)制構(gòu)造函數(shù)

...};類名::類(const類名&對象名)//復(fù)制構(gòu)造函數(shù)的實現(xiàn){函數(shù)體}4.3.2復(fù)制構(gòu)造函數(shù)4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)26第二十六頁,共87頁。復(fù)制構(gòu)造函數(shù)被調(diào)用的三種情況定義一個對象時,以本類另一個對象作為初始值,發(fā)生復(fù)制構(gòu)造;如果函數(shù)的形參是類的對象,調(diào)用函數(shù)時,將使用實參對象初始化形參對象,發(fā)生復(fù)制構(gòu)造;如果函數(shù)的返回值是類的對象,函數(shù)執(zhí)行完成返回主調(diào)函數(shù)時,將使用return語句中的對象初始化一個臨時無名對象,傳遞給主調(diào)函數(shù),此時發(fā)生復(fù)制構(gòu)造。4.3.2復(fù)制構(gòu)造函數(shù)4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)27第二十七頁,共87頁。classPoint{//Point類的定義public: Point(intxx=0,intyy=0){x=xx;y=yy;}//構(gòu)造函數(shù),內(nèi)聯(lián) Point(constPoint&p);//復(fù)制構(gòu)造函數(shù)voidsetX(intxx){x=xx;}voidsetY(intyy){y=yy;} intgetX()const{returnx;}//常函數(shù)(第5章) intgetY()const{returny;}//常函數(shù)(第5章)private: intx,y;//私有數(shù)據(jù)};//成員函數(shù)的實現(xiàn)Point::Point(constPoint&p){x=p.x;y=p.y;cout<<"Callingthecopyconstructor"<<endl;}例4-2Point類的完整程序4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.2復(fù)制構(gòu)造函數(shù)28第二十八頁,共87頁。//形參為Point類對象的函數(shù)voidfun1(Pointp){ cout<<p.getX()<<endl;}//返回值為Point類對象的函數(shù)Pointfun2(){ Pointa(1,2); returna;}

//主程序intmain(){ Pointa(4,5); //第一個對象A Pointb=a; //情況一,用A初始化B。第一次調(diào)用復(fù)制構(gòu)造函數(shù)

cout<<b.getX()<<endl; fun1(b); //情況二,對象B作為fun1的實參。第二次調(diào)用復(fù)制構(gòu)造函數(shù)

b=fun2(); //情況三,函數(shù)的返回值是類對象,函數(shù)返回時調(diào)用復(fù)制構(gòu)造函數(shù)

cout<<b.getX()<<endl; return0;}例4-2(續(xù))4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.2復(fù)制構(gòu)造函數(shù)29第二十九頁,共87頁。傳遞對象值會引起復(fù)制構(gòu)造和析構(gòu),增加時間空間開銷。傳常引用可避免這一問題。以引用做參數(shù)時,盡量使用常引用。(第5章)例如:voidfun1(constPoint&p){ cout<<p.getX()<<endl;p.setX(1);//語法錯誤:p是常引用而setX不是常函數(shù)}基本類型、STL的迭代器和函數(shù)對象傳值較好。(第12章)*函數(shù)參數(shù)盡量傳遞常引用而不是值30第三十頁,共87頁。當(dāng)函數(shù)返回一個對象時,會構(gòu)造臨時對象用以返回,這會增加開銷。用返回引用或者指針替代不是好辦法。返回指向局部對象的指針或者引用,會引發(fā)錯誤。返回指向動態(tài)內(nèi)存的指針或引用容易忘記動態(tài)空間釋放,引起內(nèi)存泄露。解決顯式構(gòu)造臨時對象返回。此舉表面上還是構(gòu)造了一個臨時對象,但是編譯器通常都會進(jìn)行優(yōu)化,使之不產(chǎn)生臨時對象。例如:Pointfun2(){ returnPoint(1,2);}*返回值優(yōu)化31第三十一頁,共87頁。如果程序員沒有為類聲明復(fù)制構(gòu)造函數(shù),則編譯器自己生成一個隱含的復(fù)制構(gòu)造函數(shù)。這個構(gòu)造函數(shù)執(zhí)行的功能是:用作為初始值的對象的每個數(shù)據(jù)成員的值,初始化將要建立的對象的對應(yīng)數(shù)據(jù)成員。隱含的復(fù)制構(gòu)造函數(shù)4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.2復(fù)制構(gòu)造函數(shù)32第三十二頁,共87頁。完成對象被刪除前的一些清理工作。在對象的生存期結(jié)束的時刻系統(tǒng)自動調(diào)用它,然后再釋放此對象所屬的空間。如果程序中未聲明析構(gòu)函數(shù),編譯器將自動產(chǎn)生一個隱含的析構(gòu)函數(shù)。4.3.3析構(gòu)函數(shù)4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)33第三十三頁,共87頁。#include<iostream>usingnamespacestd;classPoint{public:Point(intxx,intyy);~Point();//...其他函數(shù)原型private:intx,y;};構(gòu)造函數(shù)和析構(gòu)函數(shù)舉例4.3構(gòu)造函數(shù)和析構(gòu)函數(shù)——4.3.3析構(gòu)函數(shù)Point::Point(intxx,intyy){x=xx;y=yy;}Point::~Point(){}//...其他函數(shù)的實現(xiàn)略34第三十四頁,共87頁。classEmpty{public:

Empty(){}Empty(constEmpty&rhs){…}~Empty(){}Emptyoperator=(constEmpty&rhs){…}};*編譯器默認(rèn)提供的函數(shù)35第三十五頁,共87頁。有些類,不應(yīng)該有默認(rèn)初始化。例如,沒有姓名的學(xué)生對象是沒有意義的解決:至少定義一個有參數(shù)的構(gòu)造函數(shù)不定義默認(rèn)構(gòu)造函數(shù)需要深層復(fù)制時,默認(rèn)的復(fù)制構(gòu)造會引起錯誤。(見第6章)解決:自定義實現(xiàn)深層復(fù)制的復(fù)制構(gòu)造函數(shù)*有時不應(yīng)該有默認(rèn)的構(gòu)造函數(shù)36第三十六頁,共87頁。例如,房屋中介系統(tǒng)有一個類描述待售房屋classHomeForSale{…}通常沒有完全一樣的房屋,因此不應(yīng)有復(fù)制構(gòu)造解決方法一:將不應(yīng)該有的默認(rèn)函數(shù)定義為私有classHomeForSale{public:…private:…HomeForSale(constHomeForSale&);HomeForSale&operator=(constHomeForSale&)

//重載賦值運算符見第8章};*有時不應(yīng)該進(jìn)行復(fù)制和賦值37第三十七頁,共87頁。解決方法二:定義一個Uncopyable類作為基類(類的繼承見第7章)classUncopyable{protected:Uncopyable(){}~Uncopyable(){}private:Uncopyable(constUncopyable&);Uncopyableoperator=(constUncopyable&);};*有時不應(yīng)該進(jìn)行復(fù)制和賦值(續(xù))38第三十八頁,共87頁。類中的成員數(shù)據(jù)是另一個類的對象??梢栽谝延谐橄蟮幕A(chǔ)上實現(xiàn)更復(fù)雜的抽象。4.4.1組合4.4類的組合39第三十九頁,共87頁。原則:不僅要負(fù)責(zé)對本類中的基本類型成員數(shù)據(jù)賦初值,也要對對象成員初始化。聲明形式:類名::類名(對象成員所需的形參,本類成員形參):對象1(參數(shù)),對象2(參數(shù)),......{//函數(shù)體其他語句}類組合的構(gòu)造函數(shù)設(shè)計4.4類的組合——4.4.1組合40第四十頁,共87頁。首先對構(gòu)造函數(shù)初始化列表中列出的成員(包括基本類型成員和對象成員)進(jìn)行初始化,初始化次序是成員在類體中定義的次序。成員對象構(gòu)造函數(shù)調(diào)用順序:按對象成員的聲明順序,先聲明者先構(gòu)造。初始化列表中未出現(xiàn)的成員對象,調(diào)用用默認(rèn)構(gòu)造函數(shù)(即無形參的)初始化處理完初始化列表之后,再執(zhí)行構(gòu)造函數(shù)的函數(shù)體。構(gòu)造組合類對象時的初始化次序4.4類的組合——4.4.1組合41第四十一頁,共87頁。//4_4.cpp#include<iostream>#include<cmath>usingnamespacestd;classPoint{ //Point類定義public: Point(intxx=0,intyy=0){ x=xx; y=yy; } Point(Point&p); intgetX(){returnx;} intgetY(){returny;}private: intx,y;};Point::Point(Point&p){ //復(fù)制構(gòu)造函數(shù)的實現(xiàn)

x=p.x; y=p.y; cout<<"CallingthecopyconstructorofPoint"<<endl;}例4-4類的組合,線段(Line)類4.4類的組合——4.4.1組合42第四十二頁,共87頁。//類的組合classLine{ //Line類的定義public: //外部接口

Line(Pointxp1,Pointxp2); Line(Line&l); doublegetLen(){returnlen;}private: //私有數(shù)據(jù)成員

Pointp1,p2; //Point類的對象p1,p2 doublelen;};//組合類的構(gòu)造函數(shù)Line::Line(Pointxp1,Pointxp2):p1(xp1),p2(xp2){ cout<<"CallingconstructorofLine"<<endl; doublex=static_cast<double>(p1.getX()-p2.getX()); doubley=static_cast<double>(p1.getY()-p2.getY()); len=sqrt(x*x+y*y);}Line::Line(Line&l):p1(l.p1),p2(l.p2){//組合類的復(fù)制構(gòu)造函數(shù) cout<<"CallingthecopyconstructorofLine"<<endl; len=l.len;}例4-4(續(xù))4.4類的組合——4.4.1組合43第四十三頁,共87頁。//主函數(shù)intmain(){ Pointmyp1(1,1),myp2(4,5); //建立Point類的對象

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

Lineline2(line); //利用復(fù)制構(gòu)造函數(shù)建立一個新對象

cout<<"Thelengthofthelineis:"; cout<<line.getLen()<<endl; cout<<"Thelengthoftheline2is:"; cout<<line2.getLen()<<endl; return0;}例4-4(續(xù))4.4類的組合——4.4.1組合運行結(jié)果如下:CallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingconstructorofLineCallingthecopyconstructorofPointCallingthecopyconstructorofPointCallingthecopyconstructorofLineThelengthofthelineis:5Thelengthoftheline2is:544第四十四頁,共87頁。類應(yīng)該先聲明,后使用如果需要在某個類的聲明之前,引用該類,則應(yīng)進(jìn)行前向引用聲明。前向引用聲明只為程序引入一個標(biāo)識符,但具體聲明在其他地方。4.4.2前向引用聲明4.4類的組合45第四十五頁,共87頁。classB;//前向引用聲明classA{public:voidf(Bb);};classB{public:voidg(Aa);};舉例4.4類的組合——4.4.2前向引用聲明46第四十六頁,共87頁。使用前向引用聲明雖然可以解決一些問題,但它并不是萬能的。需要注意的是,盡管使用了前向引用聲明,但是在提供一個完整的類聲明之前,不能聲明該類的對象,也不能在內(nèi)聯(lián)成員函數(shù)中使用該類的對象。請看下面的程序段:前向引用聲明注意事項4.4類的組合——4.4.2前向引用聲明classFred;//前向引用聲明classBarney{Fredx;//錯誤:類Fred的聲明尚不完善};classFred{Barneyy;};47第四十七頁,共87頁。classFred; //前向引用聲明

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

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

classFred{public:voidyabbaDabbaDo();private:Barney&y;};前向引用聲明注意事項(續(xù))4.4類的組合——4.4.2前向引用聲明48第四十八頁,共87頁。應(yīng)該記?。寒?dāng)你使用前向引用聲明時,你只能使用被聲明的符號,而不能涉及類的任何細(xì)節(jié)。前向引用聲明注意事項(續(xù))4.4類的組合——4.4.2前向引用聲明49第四十九頁,共87頁。UML(UnifiedModelingLanguage)語言是一種可視化的的面向?qū)ο蠼UZ言。UML有三個基本的部分事物(Things)

UML中重要的組成部分,在模型中屬于最靜態(tài)的部分,代表概念上的或物理上的元素關(guān)系(Relationships)

關(guān)系把事物緊密聯(lián)系在一起圖(Diagrams)

圖是很多有相互相關(guān)的事物的組4.5.1UML簡介4.5UML圖形標(biāo)識50第五十頁,共87頁。舉例:Clock類的完整表示Clock類的簡潔表示4.5.2UML類圖4.5UML圖形標(biāo)識Clock-hour:int-minute:int-second:int+showTime():void+setTime(newH:int=0,newM:int=0,newS:int=0):voidClock51第五十一頁,共87頁。數(shù)據(jù)成員的語法:[訪問控制屬性]名稱[重數(shù)][:類型][=默認(rèn)值][{約束特征}]函數(shù)成員的語法:[訪問控制屬性]名稱[(參數(shù)表)][:返回類型][{約束特性}]

參數(shù)表:[方向]名稱:類型=默認(rèn)值UML類圖52第五十二頁,共87頁。對象圖4.5UML圖形標(biāo)識——4.5.2UML類圖myClock:Clock-hour:int-minute:int-second:intmyClock:Clock53第五十三頁,共87頁。依賴關(guān)系圖中的“類A”是源,“類B”是目標(biāo),表示“類A”使用了“類B”,或稱“類A”依賴“類B”幾種關(guān)系的圖形標(biāo)識4.5UML圖形標(biāo)識——4.5.2UML類圖類A類B54第五十四頁,共87頁。作用關(guān)系——關(guān)聯(lián)圖中的“重數(shù)A”決定了類B的每個對象與類A的多少個對象發(fā)生作用,同樣“重數(shù)B”決定了類A的每個對象與類B的多少個對象發(fā)生作用。幾種關(guān)系的圖形標(biāo)識4.5UML圖形標(biāo)識——4.5.2UML類圖類A重數(shù)A類B重數(shù)B55第五十五頁,共87頁。包含關(guān)系——聚集和組合

共享聚集

組成聚集(簡稱組合)聚集表示類之間的關(guān)系是整體與部分的關(guān)系,“包含”、“組成”、“分為……部分”等都是聚集關(guān)系。共享聚集:部分可以參加多個整體;組成聚集:整體擁有各個部分,整體與部分共存,如果整體不存在了,那么部分也就不存在了。幾種關(guān)系的圖形標(biāo)識4.5UML圖形標(biāo)識——4.5.2UML類圖類A類B重數(shù)A重數(shù)B類A類B重數(shù)A重數(shù)B56第五十六頁,共87頁。例4-5采用UML方法來描述例4-4中Line類和Point類的關(guān)系4.5UML圖形標(biāo)識——4.5.2UML類圖Point-x:int-y:int+Point(xx:int=0,yy:int=0)+Point(p:Point&)+getX():int+getY():intLine-len:double+Line(xp1:Point,xp2:Point)+Line(:Line&)+getLen():double-p1-p21..*21..*57第五十七頁,共87頁。繼承關(guān)系——泛化

幾種關(guān)系的圖形標(biāo)識4.5UML圖形標(biāo)識——4.5.2UML類圖父類A父類B子類1子類258第五十八頁,共87頁。在UML圖形上,注釋表示為帶有褶角的矩形,然后用虛線連接到UML的其他元素上,它是一種用于在圖中附加文字注釋的機(jī)制。注釋4.5UML圖形標(biāo)識——4.5.2UML類圖注釋文字59第五十九頁,共87頁。例4-6帶有注釋的Line類和Point類關(guān)系的描述4.5UML圖形標(biāo)識——4.5.2UML類圖Point-x:int-y:int+Point(xx:int=0,yy:int=0)+Point(p:Point&)+getX():int+getY():intLine-len:double+Line(xp1:Point,xp2:Point)+Line(:Line&)+getLen():double-p1-p21..*21..*單向組合:直線段包含端點p1、p260第六十頁,共87頁。結(jié)構(gòu)體是一種特殊形態(tài)的類與類的唯一區(qū)別:類的缺省訪問權(quán)限是private,結(jié)構(gòu)體的缺省訪問權(quán)限是public結(jié)構(gòu)體存在的主要原因:與C語言保持兼容什么時候用結(jié)構(gòu)體而不用類定義主要用來保存數(shù)據(jù)、而沒有什么操作的類型人們習(xí)慣將結(jié)構(gòu)體的數(shù)據(jù)成員設(shè)為公有,因此這時用結(jié)構(gòu)體更方便4.6.1結(jié)構(gòu)體4.6結(jié)構(gòu)體和聯(lián)合體61第六十一頁,共87頁。結(jié)構(gòu)體定義struct結(jié)構(gòu)體名稱{

公有成員protected:

保護(hù)型成員private:

私有成員};一些結(jié)構(gòu)體變量的初始化可以用以下形式類型名變量名

={成員數(shù)據(jù)1初值,成員數(shù)據(jù)2初值,……};結(jié)構(gòu)體的定義和初始化4.6結(jié)構(gòu)體和聯(lián)合體——4.6.1結(jié)構(gòu)體62第六十二頁,共87頁。#include<iostream>#include<iomanip>#include<string>usingnamespacestd;structStudent{ //學(xué)生信息結(jié)構(gòu)體

intnum; //學(xué)號

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

charsex; //性別

intage; //年齡};例4-7用結(jié)構(gòu)體表示學(xué)生的基本信息4.6結(jié)構(gòu)體和聯(lián)合體——4.6.1結(jié)構(gòu)體63第六十三頁,共87頁。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;}運行結(jié)果:Num:97001Name:LinLinSex:FAge:19例4-7(續(xù))4.6結(jié)構(gòu)體和聯(lián)合體——4.6.1結(jié)構(gòu)體64第六十四頁,共87頁。聲明形式union聯(lián)合體名稱{公有成員protected:

保護(hù)型成員private:

私有成員};特點:成員共用相同的內(nèi)存單元任何兩個成員不會同時有效4.6.2聯(lián)合體4.6結(jié)構(gòu)體和聯(lián)合體65第六十五頁,共87頁。unionMark{ //表示成績的聯(lián)合體 chargrade; //等級制的成績

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

intpercent; //百分制的成績};聯(lián)合體的內(nèi)存分配4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體Markgradepercentpass66第六十六頁,共87頁。例:union{inti;floatf;}在程序中可以這樣使用:i=10;f=2.2;無名聯(lián)合4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體無名聯(lián)合沒有標(biāo)記名,只是聲明一個成員項的集合,這些成員項具有相同的內(nèi)存地址,可以由成員項的名字直接訪問。67第六十七頁,共87頁。#include<string>#include<iostream>usingnamespacestd;classExamInfo{private: stringname; //課程名稱

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

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

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

intpercent; //百分制的成績

};例4-8使用聯(lián)合體保存成績信息,并且輸出。4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體68第六十八頁,共87頁。public:

//三種構(gòu)造函數(shù),分別用等級、是否通過和百分初始化

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();}例4-8(續(xù))4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體69第六十九頁,共87頁。voidExamInfo::show(){ cout<<name<<":"; switch(mode){ caseGRADE:cout<<grade;break; casePASS:cout<<(pass?"PASS":"FAIL");break; casePERCENTAGE:cout<<percent;break; } cout<<endl;}例4-8(續(xù))4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體70第七十頁,共87頁。intmain(){ ExamInfocourse1("English",'B'); ExamInfocourse2("Calculus",true); ExamInfocourse3("C++Programming",85); course1.show(); course2.show(); course3.show(); return0;}運行結(jié)果:English:BCalculus:PASSC++Programming:85例4-8(續(xù))4.6結(jié)構(gòu)體和聯(lián)合體——4.6.2聯(lián)合體71第七十一頁,共87頁。例4-9個人銀行賬戶管理程序(1)//4_9.cpp#include<iostream>#include<cmath>usingnamespacestd;classSavingsAccount{//儲蓄賬戶類private: intid; //賬號

doublebalance; //余額

doublerate; //存款的年利率

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

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

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

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

doubleaccumulate(intdate)const{ returnaccumulation+balance*(date-lastDate); }72第七十二頁,共87頁。例4-9個人銀行賬戶管理程序(2)public: //構(gòu)造函數(shù)

SavingsAccount(intdate,intid,doublerate); intgetId(){returnid;} doublegetBalance(){returnbalance;} doublegetRate(){returnrate;} //存入現(xiàn)金

voiddeposit(intdate,doubleamount); //取出現(xiàn)金

voidwithdraw(intdate,doubleamount); //結(jié)算利息,每年1月1日調(diào)用一次該函數(shù)

voidsettle(intdate); //顯示賬戶信息

voidshow();};73第七十三頁,共87頁。例4-9個人銀行賬戶管理程序(3)//SavingsAccount類相關(guān)成員函數(shù)的實現(xiàn)SavingsAccount::SavingsAccount(intdate,intid,doublerate) :id(id),balance(0),rate(rate),lastDate(date),accumulation(0){ cout<<date<<"\t#"<<id<<"iscreated"<<endl;}voidSavingsAccount::record(intdate,doubleamount){ accumulation=accumulate(date); lastDate=date; amount=floor(amount*100+0.5)/100; //保留小數(shù)點后兩位

balance+=amount; cout<<date<<"\t#"<<id<<"\t"<<amount<<"\t"<<balance<<endl;}voidSavingsAccount::deposit(intdate,doubleamount){ record(date,amount);}74第七十四頁,共87頁。例4-9個人銀行賬戶管理程序(4)voidSavingsAccount::withdraw(intdate,doubleamount){ if(amount>getBalance()) cout<<"Error:notenoughmoney"<<endl; else record(date,-amount);}voidSavingsAccount::settle(intdate){ doubleinterest=accumulate(date)*rate/365; //計算年息

if(interest!=0) record(date,interest); accumulation=0;}voidSavingsAccount::show(){ cout<<"#"<<id<<"\tBalance:"<<balance;}75第七十五頁,共87頁。例4-9個人銀行賬戶管理程序(5)intmain(){ //建立幾個賬戶

SavingsAccountsa0(1,21325302,0.015); SavingsAccountsa1(1,58320212,0.015); //幾筆賬目

sa0.deposit(5,5000); sa1.deposit(25,10000); sa0.deposit(45,5500); sa1.withdraw(60,4000); //開戶后第90天到了銀行的計息日,結(jié)算所有賬戶的年息

sa0.settle(90); sa1.settle(90); //輸出各個賬戶信息

sa0.show(); cout<<endl; sa1.show(); cout<<endl; return0;}76第七十六頁,共87頁。位域位域的聲明形式

數(shù)據(jù)類型說明符成員名:位數(shù);位域的作用通過“打包”,使類的不同成員共享相同的字節(jié),從而節(jié)省存儲空間。注意事項具體的打包方式,因編譯器而異;只有bool、char、int和枚舉類型的成員,允許定義為位域;節(jié)省空間,但可能增加時間開銷。77第七十七頁,共87頁。例4-10設(shè)計一個結(jié)構(gòu)體存儲學(xué)生的成績信息,需要包括學(xué)號、年級和成績?nèi)梼?nèi)容,學(xué)號的范圍是0到99,999,999,年級分為freshman、sophomore、junior、senior四種,成績包括A、B、C、D四個等級。78第七十八頁,共87頁。例4-10#include<iostream>usingnamespacestd;enumLevel{FRESHMAN,SOPHOMORE,JUNIOR,SENIOR};enumGrade{A,B,C,D};classStudent{public: Student(unsignednumber,Levellevel,Gradegrade) :number(number),level(le

溫馨提示

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

評論

0/150

提交評論