C++程序設(shè)計(jì)課件_第1頁(yè)
C++程序設(shè)計(jì)課件_第2頁(yè)
C++程序設(shè)計(jì)課件_第3頁(yè)
C++程序設(shè)計(jì)課件_第4頁(yè)
C++程序設(shè)計(jì)課件_第5頁(yè)
已閱讀5頁(yè),還剩580頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》教學(xué)內(nèi)容

第1章 C++概述第2章 類和對(duì)象第3章面向?qū)ο蟪绦蛟O(shè)計(jì)概述第4章進(jìn)一步學(xué)習(xí)類和對(duì)象第5章堆與復(fù)制構(gòu)造函數(shù)第6章繼承性:派生類第7章運(yùn)算符重載第8章 虛函數(shù)和多態(tài)性第9章 模板第10章類庫(kù)和C++的標(biāo)準(zhǔn)模板庫(kù)STL第11章輸入輸出流第12章異常處理第2章類和對(duì)象2.1類和對(duì)象的定義2.2構(gòu)造函數(shù)和析構(gòu)函數(shù)2.3類與const對(duì)象和類屬于同一個(gè)類的所有對(duì)象具有某些共性和相似的特征。一個(gè)類定義了一組大體上相似的對(duì)象。在面向?qū)ο蟮能浖到y(tǒng)中,對(duì)象是基本的運(yùn)行時(shí)實(shí)體,它既包含數(shù)據(jù),也包括作用于這些數(shù)據(jù)的操作。對(duì)象對(duì)象的組成操作代碼數(shù)據(jù)面向?qū)ο蟮能浖到y(tǒng)對(duì)象4對(duì)象1對(duì)象3對(duì)象2§2.1類和對(duì)象的定義2.1.1

C++中對(duì)結(jié)構(gòu)的擴(kuò)展2.1.2

C++中類的定義2.1.3

C++類中的成員函數(shù)定義2.1.4

C++中對(duì)象的定義和使用2.1.5

C++中類的接口與實(shí)現(xiàn)2.1.6類聲明與類定義2.1.7結(jié)構(gòu)struct與類class的比較2.1.1

C++中對(duì)結(jié)構(gòu)的擴(kuò)展C++中的結(jié)構(gòu)不僅可以包含不同類型的數(shù)據(jù),而且還可以包含函數(shù)。結(jié)構(gòu)中的數(shù)據(jù)和函數(shù)都是結(jié)構(gòu)的成員,分別稱為數(shù)據(jù)成員和函數(shù)成員。在C++中,通常把函數(shù)成員稱為成員函數(shù)。C的結(jié)構(gòu)體struct與C++的struct的比較C語(yǔ)言的結(jié)構(gòu)體中數(shù)據(jù)與操作是分離的

在C++語(yǔ)言中將數(shù)據(jù)與操作封裝在一個(gè)結(jié)構(gòu)體中

structStudent{ intnumber; charname[15]; floatscore;};數(shù)據(jù)成員structStudent{intnumber;charname[15];floatscore;voiddisplay()//函數(shù)成員{ cout<<”number:”<<number; cout<<”name:”<<name; cout<<”score:”<<score<<endl;}};/*獨(dú)立函數(shù)display*/voiddisplay(Student*stu){ printf(”number:%d”,stu->number); printf(”name:%s”,stu->name); printf(”score:%f\n”,stu->score);}成員函數(shù)數(shù)據(jù)成員2.1.2

C++中類的定義在C++語(yǔ)言中,我們通過(guò)定義新的數(shù)據(jù)類型來(lái)實(shí)現(xiàn)類。類既包含數(shù)據(jù)內(nèi)容又包含對(duì)數(shù)據(jù)的操作,所以類是一個(gè)抽象數(shù)據(jù)類型。在C++語(yǔ)言中,類可被視為一種用戶定義的類型。C++的結(jié)構(gòu)體struct與C++的class的比較將數(shù)據(jù)與操作封裝在一個(gè)C++的結(jié)構(gòu)體struct中將數(shù)據(jù)與操作封裝在一個(gè)C++類class中數(shù)據(jù)成員structStudent{intnumber;charname[15];floatscore;voiddisplay()//函數(shù)成員{ cout<<”number:”<<number; cout<<”name:”<<name; cout<<”score:”<<score<<endl;}};數(shù)據(jù)成員class

Student{intnumber;charname[15];floatscore;voiddisplay()//函數(shù)成員{ cout<<”number:”<<number; cout<<”name:”<<name; cout<<”score:”<<score<<endl;}};成員函數(shù)數(shù)據(jù)成員一個(gè)復(fù)數(shù)結(jié)構(gòu)的例子structcomplex{doublereal;doubleimage;voidinit(doubler,doublei){real=r;image=i;}doublerealcomplex(){returnreal;}…;};成員函數(shù)數(shù)據(jù)成員私有成員和公有成員在C++中一個(gè)結(jié)構(gòu)的成員通常分為兩類:私有成員(private)和公有成員(

public)私有成員只能被該結(jié)構(gòu)中的其他成員訪問(wèn)。公有成員既可以被結(jié)構(gòu)內(nèi)的其他成員訪問(wèn),也可以被結(jié)構(gòu)外的成員所訪問(wèn)。C++規(guī)定,在缺省情況下,結(jié)構(gòu)中的成員是公有的。此處所指成員包括數(shù)據(jù)成員和成員函數(shù)。私有成員和公有成員的聲明structcomplex{private:doublereal;doubleimage;public:voidinit(doubler,doublei){real=r;image=i;}doublerealcomplex(

){returnreal;}…;};私有成員公有成員類的定義class

類名{[private:]

私有數(shù)據(jù)成員和成員函數(shù)public:

公有數(shù)據(jù)成員和成員函數(shù)};//分號(hào)是不能少的//其中,class是聲明類的關(guān)鍵字//類名是要聲明的類的名字類中私有成員和公有成員的聲明classcomplex{private:doublereal;doubleimage;public:voidinit(doubler,doublei){real=r;image=i;}doublerealcomplex(){returnreal;}…;};私有成員公有成員定義類時(shí)的注意事項(xiàng)private和public可以按任意順序出現(xiàn)具有良好習(xí)慣的程序員會(huì):把所有私有成員和公有成員歸類放在一起將私有成員放在公有成員的前面private、public和protected稱為訪問(wèn)控制符。數(shù)據(jù)成員可以是任何數(shù)據(jù)類型,但不能用auto、register或extern進(jìn)行說(shuō)明。只有在類對(duì)象定義之后才能給數(shù)據(jù)成員賦初值。為什么要用類代替結(jié)構(gòu)?在缺省情況下,類中的成員是私有的private。類提供了缺省的安全性。2.1.3

C++類中的成員函數(shù)定義C++類中的成員函數(shù)描述了對(duì)類對(duì)象內(nèi)部數(shù)據(jù)的操作方法,或者說(shuō),描述了對(duì)象的行為,因此我們又將成員函數(shù)稱為方法(method)或者服務(wù)(service)。【例2.2】學(xué)生類中成員函數(shù)的定義。成員函數(shù)的定義包含在類體中classStudent{private: intnumber; charname[15]; floatscore;public: voidinit(intnumber1,char*name1,floatscore1);

voidmodify(floatscore1) { score=score1; } voidprint();};成員函數(shù)在類體外定義voidStudent::init(intnumber1,char*name1,floatscore1){作用域解析運(yùn)算符

number=number1; strcpy(name,name1); score=score1;}voidStudent::print(){ cout<<”number:”<<number<<”name:”<<name<<”score:”<<score<<’\n’;}成員函數(shù)在類體內(nèi)外的區(qū)別一般情況下,在類體中僅給出成員函數(shù)的原型,而把成員函數(shù)的定義放在類體之外實(shí)現(xiàn)。這種將類的成員函數(shù)的聲明(declaration)和定義(definition)進(jìn)行分離的方式有很多好處類體內(nèi)定義的成員函數(shù)在編譯時(shí)是以內(nèi)聯(lián)函數(shù)處理的,只有那些非常簡(jiǎn)短的函數(shù)才在類體中直接定義。2.1.4

C++中對(duì)象的定義和使用在C++語(yǔ)言中,類是用戶定義的一種新類型,所以可以象聲明普通變量一樣來(lái)建立對(duì)象。在C++語(yǔ)言中,類與對(duì)象的關(guān)系就好象整型int和整型變量i之間的關(guān)系一樣。注意:所有類對(duì)象都共享它們的成員函數(shù),但是,每一個(gè)對(duì)象都建立并保持自己的數(shù)據(jù)。對(duì)象的數(shù)據(jù)成員,在C++中稱為實(shí)例變量。創(chuàng)建對(duì)象的方法之一在定義類時(shí)同時(shí)創(chuàng)建對(duì)象,例如:classdate{intmonth,day,year;public:voidsetdate(int,int,int);voidprint();intgetyear();intgetmonth();intgetday();}tt;//同時(shí)創(chuàng)建對(duì)象tt。創(chuàng)建對(duì)象的方法之二在定義類后在創(chuàng)建對(duì)象,例如:Datadate1,date2;對(duì)象的使用對(duì)象的性質(zhì)和定義要求將實(shí)例變量隱藏在對(duì)象中,對(duì)它們的訪問(wèn),原則上要通過(guò)其接口——共有的成員函數(shù)來(lái)進(jìn)行。訪問(wèn)對(duì)象的成員時(shí),使用“.”運(yùn)算符:對(duì)象名.成員名稱;調(diào)用成員函數(shù)是必須指明對(duì)象,事實(shí)上,在C++語(yǔ)言中,我們用OOP術(shù)語(yǔ)發(fā)送消息來(lái)代替“調(diào)用成員函數(shù)”這個(gè)說(shuō)法。2.1.5

C++中類的接口與實(shí)現(xiàn)一般把僅含函數(shù)原型的類聲明部分稱為類的接口(interface),例如:classDate{ intday,month,year;public: voidinit(intdd,intmm,intyy);//initialize voidadd_year(intn); //addnyears voidadd_month(intn);//addnmonths voidadd_day(intn); //addndays}C++中類的接口與實(shí)現(xiàn)(續(xù))把類中成員函數(shù)的定義部分稱為類的實(shí)現(xiàn)部分(implementation)。例如:voidDate::init(intdd,intmm,intyy){ day=dd; month=mm; year=yy;}inlinevoidDate::add_year(intn){ year+=n;}C++中類的接口與實(shí)現(xiàn)(續(xù))C++中的類實(shí)現(xiàn)了接口和實(shí)現(xiàn)的分離,這樣只要維持接口不變,實(shí)現(xiàn)部分可以根據(jù)需要不斷改進(jìn),而不影響類的使用。類的接口部分一般存放在擴(kuò)展名為h的頭文件中,類的實(shí)現(xiàn)部分則存放在擴(kuò)展名為cpp的實(shí)現(xiàn)文件中。在cpp文件的開頭要用include將h頭文件包含在其中。這個(gè)特征增強(qiáng)了類模塊的獨(dú)立性和可重用性(reuse)。設(shè)計(jì)一個(gè)類(class)時(shí)的基本原則在設(shè)計(jì)一個(gè)新的類(class)類型時(shí)的基本原則是將類的復(fù)雜的實(shí)現(xiàn)細(xì)節(jié)(例如用來(lái)存儲(chǔ)該類對(duì)象的數(shù)據(jù))和正確使用該類所需知道的要素(例如訪問(wèn)對(duì)象數(shù)據(jù)的函數(shù))分離開來(lái)。這種分離的最好方式就是通過(guò)一個(gè)特定的接口來(lái)使用該類的數(shù)據(jù)結(jié)構(gòu)和內(nèi)部處理程序。封裝(encapsulation)在進(jìn)行類定義時(shí),我們把需要提供給類的用戶的在類對(duì)象上執(zhí)行的操作聲明為公用的(public),這樣就形成了類的接口。然后按照信息隱藏(informationhiding)的原則來(lái)把類的內(nèi)部數(shù)據(jù)表示和實(shí)現(xiàn)細(xì)節(jié)聲明為私有的(private),從而完成了封裝(encapsulation)。封裝性及其好處所謂封裝,在面向?qū)ο蟪绦蛟O(shè)計(jì)中的含義就是包含和隱藏對(duì)象信息,如內(nèi)部數(shù)據(jù)結(jié)構(gòu)和代碼的能力。在C++中封裝是通過(guò)類來(lái)實(shí)現(xiàn)的,即將內(nèi)部的數(shù)據(jù)和代碼聲明為私有的,外界不能直接訪問(wèn)。封裝將操作對(duì)象的內(nèi)部復(fù)雜性與應(yīng)用程序的其他部分隔離開來(lái)。換句話說(shuō),應(yīng)用類對(duì)象的程序員不需要知道類內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)就可以使用該類。這是面向?qū)ο蟪绦蛟O(shè)計(jì)降低復(fù)雜性的最主要途徑。2.1.6類聲明與類定義類定義包含兩部分:類頭和類體,類體由一對(duì)花括號(hào)包圍起來(lái)。一旦到了類體的結(jié)尾,即結(jié)束右邊的花括號(hào),這時(shí)就定義了一個(gè)類。一旦定義了一個(gè)類,則該類的所有成員就都是已知的,類的大小也是已知的了。類聲明由于歷史的原因,類的定義(classdefinition)也稱為類的聲明(declaration)。但是準(zhǔn)確地說(shuō),一旦給出了類頭,就聲明了一個(gè)類。我們可以聲明一個(gè)類但是不定義它。例如:classDate;//Date類的聲明這個(gè)聲明向程序引入了一個(gè)名字Date,指示Date為一個(gè)類類型。類聲明(續(xù))如果還沒(méi)有定義類,那么我們就不能定義這類類型的對(duì)象但是,我們可以聲明指向這種類型對(duì)象的指針或者引用。classDate; //Date類的聲明Datepd,&rd;//聲明了指向Date類對(duì)象的指針pd和引用rd2.1.7結(jié)構(gòu)struct與類class的比較結(jié)構(gòu)和類的唯一區(qū)別是:在缺省情況下結(jié)構(gòu)內(nèi)數(shù)據(jù)成員和成員函數(shù)是公有的public,而類中的數(shù)據(jù)成員和成員函數(shù)是私有的private??梢哉f(shuō)C++中的結(jié)構(gòu)是一種特殊的類。類(或者結(jié)構(gòu))的私有成員只能被該類(或者結(jié)構(gòu))的成員函數(shù)訪問(wèn),這是C++實(shí)現(xiàn)封裝的一種方法。§2.2構(gòu)造函數(shù)和析構(gòu)函數(shù)2.2.1構(gòu)造函數(shù)2.2.2析構(gòu)函數(shù)2.2.3重載構(gòu)造函數(shù)2.2.4組合類和對(duì)象成員的初始化2.2.1構(gòu)造函數(shù)constructor構(gòu)造函數(shù)是類的一種特殊成員函數(shù),用來(lái)為對(duì)象進(jìn)行初始化。構(gòu)造函數(shù)的函數(shù)名與類名相同。構(gòu)造函數(shù)的例子1classDate{

intday,month,year;

Date(intdd,intmm,intyy);//constructor};//構(gòu)造函數(shù)名與類名相同voidDate::Date(intdd,intmm,intyy){ day=dd; month=mm; year=yy;}用來(lái)為對(duì)象進(jìn)行初始化。構(gòu)造函數(shù)的例子2classStudent{private: intnumber; charname[15]; floatscore;public: Student(intnumber1,char*name1,floatscore1);voidmodify(floatscore1) {score=score1;} voidprint();};構(gòu)造函數(shù)的聲明構(gòu)造函數(shù)的例子2//構(gòu)造函數(shù)的定義Student::Student(intnumber1,char*name1,floatscore1){ number=number1; strcpy(name,name1); score=score1;}構(gòu)造函數(shù)(續(xù))構(gòu)造函數(shù)可以有任一類型的參數(shù),但不能具有返回類型。當(dāng)定義一個(gè)對(duì)象時(shí),系統(tǒng)自動(dòng)調(diào)用構(gòu)造函數(shù)進(jìn)行初始化。構(gòu)造函數(shù)與其它函數(shù)一樣可以重載也可以有缺省參數(shù)。在對(duì)象生成的時(shí)候自動(dòng)執(zhí)行初始化,這會(huì)消除任何錯(cuò)誤地不執(zhí)行初始化的可能。這是C++面向?qū)ο蟪绦蛟O(shè)計(jì)幫助減少?gòu)?fù)雜性的另一途徑。有缺省參數(shù)的構(gòu)造函數(shù)classcomplex{private:doublereal;doubleimage;public:voidcomplex(doubler=0.0,doublei=0.0){real=r;image=i;}doublerealcomplex(){returnreal;}…;};缺省參數(shù)2.2.2析構(gòu)函數(shù)析構(gòu)函數(shù)的作用與構(gòu)造函數(shù)正好相反,當(dāng)對(duì)象被刪除時(shí),利用析構(gòu)函數(shù)進(jìn)行一些善后處理。一般情況下析構(gòu)函數(shù)執(zhí)行構(gòu)造函數(shù)的逆操作,例如可以利用析構(gòu)函數(shù)來(lái)釋放構(gòu)造函數(shù)所動(dòng)態(tài)申請(qǐng)的內(nèi)存空間。析構(gòu)函數(shù)的名稱與其類名稱相同,并在名稱的前邊加~(鍵盤上的波浪符號(hào))符號(hào)。一個(gè)類中只能有一個(gè)析構(gòu)函數(shù)。(不能重載)析構(gòu)函數(shù)不允許有返回值,并且析構(gòu)函數(shù)不允許帶參數(shù)。參見【例2.7】。構(gòu)造函數(shù)和析構(gòu)函數(shù)的例子//構(gòu)造函數(shù)的定義Student::Student(intnumber1,char*name1,floatscore1){ number=number1; name=newchar[strlen(name1)+1];//申請(qǐng)動(dòng)態(tài)內(nèi)存單元

strcpy(name,name1); score=score1;}//析構(gòu)函數(shù)的定義Student::~Student(){

delete[]name;//釋放動(dòng)態(tài)內(nèi)存單元}2.2.3重載構(gòu)造函數(shù)構(gòu)造函數(shù)與其它函數(shù)一樣可以重載也可以有缺省參數(shù)。要重載類的構(gòu)造函數(shù),只需要在類中聲明構(gòu)造函數(shù)的不同函數(shù)原型并且定義相關(guān)的函數(shù)體。重載構(gòu)造函數(shù)主要有三個(gè)原因

1.

為了獲得靈活性:提供給用戶多種初始化對(duì)象的選項(xiàng)。2.

為了支持?jǐn)?shù)組:要聲明一個(gè)類的對(duì)象數(shù)組則該類應(yīng)具有一個(gè)不帶參數(shù)的構(gòu)造函數(shù)。3.為了自定義復(fù)制構(gòu)造函數(shù),將對(duì)象進(jìn)行準(zhǔn)確的復(fù)制(拷貝):參見第5章堆與復(fù)制構(gòu)造函數(shù)。

重載構(gòu)造函數(shù)例一classDate{ intd,m,y;public://... Date(int,int,int);//day,month,year Date(int,int);//day,month,today’syear Date(int);//day,today’smonthandyear Date();//defaultDate:today Date(constchar*);//dateinstringrepresentation};為了獲得靈活性:提供給用戶多種初始化對(duì)象的選項(xiàng)2.2.4組合類和對(duì)象成員的初始化當(dāng)一個(gè)類的對(duì)象作為一個(gè)類的成員時(shí),稱為該類的對(duì)象成員。使用對(duì)象成員著重要注意的問(wèn)題是一個(gè)類的內(nèi)部對(duì)象的初始化問(wèn)題。類的對(duì)象成員初始化#include"iostream.h"classinner_class{ intx;public: inner_class(intz){x=z;} voidwrite(){cout<<x<<endl;}};類的對(duì)象成員初始化(續(xù))classouter_class{ inty; inner_classx; inner_classr;public: outer_class(intz); voidwrite(){cout<<y<<endl;} voidwrite_inner_x() {x.inner_class::write();} voidwrite_inner_r() {r.inner_class::write();}};注意:outer_class類對(duì)象在通過(guò)構(gòu)造函數(shù)進(jìn)行初始化的同時(shí),也要對(duì)其成員對(duì)象進(jìn)行初始化。類的對(duì)象成員初始化(續(xù))outer_class::outer_class(intz):x(20),r(-36){y=z;}main(){ outer_classobj(10); obj.write_inner_x(); obj.write_inner_r(); obj.write(); return0;}初始化參數(shù)傳遞鏈初始化和撤銷的順序先里后外:先調(diào)用對(duì)象成員的構(gòu)造函數(shù),再調(diào)用外圍類的成員函數(shù)。雖然對(duì)象成員調(diào)用它們類的構(gòu)造函數(shù),但此時(shí)寫的是對(duì)象的名字,而不是類名。先外后里:當(dāng)撤銷一個(gè)包含對(duì)象成員的對(duì)象時(shí),該對(duì)象的析構(gòu)函數(shù)將先執(zhí)行,然后再調(diào)用對(duì)象成員的析構(gòu)函數(shù)?!纠?.9】對(duì)象成員的初始化。//注意:在定義Student類的構(gòu)造函數(shù)時(shí),必須綴上對(duì)象成員的名字birthdayStudent::Student(intnumber1,char*name1,floatscore1,intd1,intm1,inty1):birthday(d1,m1,y1)//對(duì)象成員birthday的初始化{ number=number1; strcpy(name,name1); score=score1;}2.3類與const軟件工程的歷史經(jīng)驗(yàn)表明,程序內(nèi)部相當(dāng)多的隱蔽錯(cuò)誤是由于無(wú)意中修改了某些數(shù)據(jù)的值造成的。對(duì)數(shù)據(jù)進(jìn)行保護(hù)是減少程序中的錯(cuò)誤,提高軟件的可靠性的有效途徑之一。在C++中還廣泛使用const關(guān)鍵字,用來(lái)實(shí)現(xiàn)對(duì)共享數(shù)據(jù)的保護(hù),提高軟件的安全性。2.3.1常成員函數(shù)

ConstantMemberFunctionsclassDate{ intd,m,y;public: intday()const{returnd;} intmonth()const{returnm;} intyear()const; //...};使用const關(guān)鍵字說(shuō)明的函數(shù)常成員函數(shù)不更新對(duì)象的數(shù)據(jù)成員。(只讀函數(shù))常成員函數(shù)(續(xù))inlineintDate::year()const//正確{ returny;}inlineintDate::year()//錯(cuò)誤{ returny;}const是函數(shù)類型的一個(gè)組成部分,因此在實(shí)現(xiàn)部分也要帶const關(guān)鍵字。遺漏了const關(guān)鍵字常成員函數(shù)(續(xù))inlineintDate::year()const{ returny++;}將出現(xiàn)編譯錯(cuò)誤信息:企圖在常成員函數(shù)中修改對(duì)象的數(shù)據(jù)成員。2.3.2常對(duì)象constantobject常對(duì)象是指對(duì)象常量,定義格式如下:<類名>const<對(duì)象名>或者

const<類名><對(duì)象名>

例如:constDatecd;常對(duì)象constantobject(續(xù))必須對(duì)常對(duì)象進(jìn)行初始化,而且不能被更新。常對(duì)象只能調(diào)用它的常成員函數(shù)。普通的對(duì)象既可以調(diào)用它的常成員函數(shù),也可以調(diào)用普通成員函數(shù)。請(qǐng)看下面的例子:常對(duì)象constantobject(續(xù))voidf(Date&d,constDate&cd){ inti=d.year();//ok d.add_year(1);//ok intj=cd.year();//ok cd.add_year(1);//錯(cuò)誤}常對(duì)象不能調(diào)用它的普通成員函數(shù)常類型cosnt

常類型的變量或?qū)ο蟊仨氝M(jìn)行初始化,而且不能被更新。常數(shù)組:數(shù)組元素不能被更新。類型說(shuō)明符const數(shù)組名[大小]...常引用:被引用的對(duì)象不能被更新。const類型說(shuō)明符&引用名常指針:指向常量的指針(1.3.2小節(jié)介紹)。C++中const關(guān)鍵字使用得很廣泛,主要目的是對(duì)共享數(shù)據(jù)的保護(hù),提高軟件的安全性?!禖++面向?qū)ο蟪绦蛟O(shè)計(jì)》教學(xué)內(nèi)容

第1章 C++概述第2章 類和對(duì)象第3章面向?qū)ο蟪绦蛟O(shè)計(jì)概述第4章進(jìn)一步學(xué)習(xí)類和對(duì)象第5章堆與復(fù)制構(gòu)造函數(shù)第6章繼承性:派生類第7章運(yùn)算符重載第8章 虛函數(shù)和多態(tài)性第9章 模板第10章類庫(kù)和C++的標(biāo)準(zhǔn)模板庫(kù)STL第11章輸入輸出流第12章異常處理金尊和“計(jì)算機(jī)和軟件的發(fā)展很快,新的概念名詞和技術(shù)手段層出不窮,可謂日新月異。停留于表面的現(xiàn)象,可以讓人眼花亂,應(yīng)接不暇。只有深入到本質(zhì),從哲學(xué)方法論的高度上看問(wèn)題,找答案,才能如庖丁解牛,游刃有余?!钡?章面向?qū)ο蟪绦蛟O(shè)計(jì)概述3.1類與對(duì)象3.2消息和方法3.3什么是面向?qū)ο蟪绦蛟O(shè)計(jì)3.4數(shù)據(jù)抽象3.5封裝性和信息隱藏3.6繼承性與軟件重用3.7多態(tài)性3.8面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言3.9面向?qū)ο蟮能浖こ?.1類與對(duì)象3.1.1對(duì)象3.1.2類3.1.3對(duì)象與類的關(guān)系對(duì)象的廣義定義什么是對(duì)象(object)?現(xiàn)實(shí)世界中的任何一個(gè)事物都可以看成是一個(gè)對(duì)象。自然的實(shí)體:一個(gè)人,一輛汽車,一個(gè)教師邏輯結(jié)構(gòu):一個(gè)銀行帳號(hào),一個(gè)學(xué)生的學(xué)籍檔案,客戶通信錄對(duì)象的特性對(duì)象是人們要研究的任何事物,其特性是:1、每一個(gè)對(duì)象必須有一個(gè)名字以區(qū)別于其它對(duì)象;2、用屬性(或叫狀態(tài))來(lái)描述它的某些特征;3、有一組操作,每一個(gè)操作決定對(duì)象的一種行為。//這是關(guān)于對(duì)象的廣義定義面向?qū)ο蟮南到y(tǒng)中的對(duì)象對(duì)象是基本的運(yùn)行時(shí)實(shí)體,它既包含數(shù)據(jù)(屬性),也包括作用與數(shù)據(jù)的操作(行為)。一個(gè)對(duì)象把屬性和行為封裝成一個(gè)整體。對(duì)象是數(shù)據(jù)和對(duì)數(shù)據(jù)的操作的結(jié)合體。從程序設(shè)計(jì)者來(lái)看,對(duì)象是一個(gè)程序模塊;從用戶來(lái)看,對(duì)象為他們提供了所希望的行為。類的例子人類水果類魚類“類”是對(duì)一組具有共同屬性特征和行為特征的對(duì)象的抽象。OOP中類的例子classStudent{ intnumber; char*name; floatscore;public:

Student(intnumber1,char*name1,floatscore1); ~Student(); voidmodify(floatscore1); voidprint();};屬性操作什么是類(class)?在C++語(yǔ)言中,我們通過(guò)定義新的數(shù)據(jù)類型來(lái)構(gòu)成類。在新的數(shù)據(jù)類型中,既包含數(shù)據(jù)內(nèi)容又包含對(duì)數(shù)據(jù)的操作。一個(gè)類所包含的方法和數(shù)據(jù)描述一組對(duì)象的共同行為和屬性。什么是類(class)?一個(gè)類定義了一個(gè)大體上相似的對(duì)象。把一組對(duì)象的共同特性加以抽象并存儲(chǔ)在一個(gè)類中的能力,是面向?qū)ο蠹夹g(shù)最重要的一點(diǎn)。對(duì)象與類的關(guān)系類是對(duì)一組性質(zhì)相同的對(duì)象的描述,是對(duì)一組數(shù)據(jù)和方法的封裝。對(duì)象則是類的具體化,是類的實(shí)例??梢赃@樣定義對(duì)象:對(duì)象是類的一個(gè)實(shí)例,包括了數(shù)據(jù)和過(guò)程。3.2消息和方法3.2.1消息3.2.2方法消息Message消息是要求某個(gè)對(duì)象執(zhí)行其中某個(gè)功能操作的規(guī)格說(shuō)明。OOP中的一條消息由消息選擇器(“消息操作”或“消息名”)及若干個(gè)參數(shù)和接受消息的對(duì)象三部分組成,例如:student1.modify(score1);消息的例子接受消息的對(duì)象參數(shù)↓↓student1.modify(score1);↑

消息名發(fā)送消息與函數(shù)調(diào)用的比較1) 函數(shù)調(diào)用可以帶或不帶參量,但消息至少帶一個(gè)參量(對(duì)象名或?qū)ο笾羔槪?;它指明接受該消息的?duì)象。消息選擇器則告訴對(duì)響應(yīng)作些什么。2) 消息名(消息選擇器或消息操作)類似于函數(shù)名,但二者之間的本質(zhì)差別在于:函數(shù)名僅代表一段可執(zhí)行的代碼,而消息名的具體功能的實(shí)現(xiàn)取決于所接受消息的對(duì)象。發(fā)送消息與函數(shù)調(diào)用的比較(續(xù))3) 函數(shù)調(diào)用是過(guò)程式(面向過(guò)程)的即“如何做(Howtodo)”,而消息則是通知式(面向?qū)ο螅┑?,即告訴對(duì)象“做什么(Whattodo)”,具體“如何做(Howtodo)”由對(duì)象根據(jù)接受到的消息自行確定。lst.sort();其中,lst代表一個(gè)鏈表對(duì)象,sort是表示排序的消息名。方法(method)“方法”對(duì)應(yīng)于對(duì)象的行為(能力),即它是實(shí)現(xiàn)對(duì)象所具有的功能操作的代碼段。在C++程序中,方法即是類中定義的成員函數(shù),它是該類對(duì)象所能執(zhí)行的操作的算法實(shí)現(xiàn)。通常每個(gè)類中包含多個(gè)方法(即C++的成員函數(shù)),每個(gè)方法由方法名(函數(shù)名+參數(shù)表)和說(shuō)明該成員函數(shù)的算法實(shí)現(xiàn)的一段代碼所組成。方法的例子voidStudent::print(){ cout<<”number:”<<number<<”name:”<<name<<”score:”<<score<<’\n’;}方法是與對(duì)象相連決定怎么做的操作執(zhí)行代碼,所以方法是實(shí)現(xiàn)每條消息具體功能的手段。3.3什么是面向?qū)ο蟪绦蛟O(shè)計(jì)3.3.1結(jié)構(gòu)化程序設(shè)計(jì)方法3.3.2面向?qū)ο蟪绦蛟O(shè)計(jì)方法表3.1程序設(shè)計(jì)方法的發(fā)展過(guò)程1957~1972:面向過(guò)程的程序設(shè)計(jì)1968~1990:面向過(guò)程的結(jié)構(gòu)化程序設(shè)計(jì)1984~今:面向?qū)ο蟮某绦蛟O(shè)計(jì)結(jié)構(gòu)化程序設(shè)計(jì)的基本思想按功能劃分模塊,分而治之。分解系統(tǒng)時(shí)按照自頂向下的順序,逐步求精。設(shè)計(jì)時(shí)使各模塊間的關(guān)系盡可能簡(jiǎn)單,功能上相對(duì)獨(dú)立,從而可單獨(dú)驗(yàn)證模塊的正確性。

結(jié)構(gòu)化程序的組成

主控模塊功能模塊1功能模塊7功能模塊2功能模塊3功能模塊6功能模塊5功能模塊4圖3.3結(jié)構(gòu)化程序的組成結(jié)構(gòu)化程序設(shè)計(jì)方法的基本特點(diǎn)把數(shù)據(jù)結(jié)構(gòu)和處理數(shù)據(jù)的操作過(guò)程分離為相互獨(dú)立的實(shí)體。用數(shù)據(jù)表達(dá)實(shí)際問(wèn)題中的信息;程序代碼則實(shí)現(xiàn)用于處理加工這些數(shù)據(jù)的算法。簡(jiǎn)而言之,就是數(shù)據(jù)和操作代碼分離。

數(shù)據(jù)和操作代碼分離產(chǎn)生的問(wèn)題給程序員增加了負(fù)擔(dān):必須確保數(shù)據(jù)和代碼匹配。當(dāng)數(shù)據(jù)結(jié)構(gòu)改變時(shí),所有相關(guān)的處理過(guò)程都要進(jìn)行相應(yīng)的修改。可維護(hù)性低。即使要對(duì)不同的數(shù)據(jù)格式(結(jié)構(gòu)和類型)作同樣的處理計(jì)算,也必須編寫不同的程序??芍赜眯圆缓?。面向?qū)ο蟪绦蛟O(shè)計(jì)用面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言中的對(duì)象和類直接模擬現(xiàn)實(shí)世界中的對(duì)象,將問(wèn)題空間直接映射到軟件空間。從而設(shè)計(jì)出盡可能直接、自然地表示問(wèn)題求解方法的軟件。面向?qū)ο蟮倪@種思維方式符合人類的自然思維習(xí)慣,使我們能夠在程序中自然地描述現(xiàn)實(shí)世界的實(shí)體和問(wèn)題,增強(qiáng)了程序代碼的可讀性,有利于控制軟件的復(fù)雜性。模塊化將一個(gè)復(fù)雜的大規(guī)模軟件系統(tǒng)劃分成幾個(gè)規(guī)模較小、相對(duì)簡(jiǎn)單的模塊,即分而治之。面向?qū)ο蟪绦蛟O(shè)計(jì)方法是按對(duì)象來(lái)劃分。面向?qū)ο蟮能浖到y(tǒng)由對(duì)象組成,對(duì)象之間通過(guò)消息傳遞互相聯(lián)系,如圖3.4所示。面向?qū)ο蟮能浖到y(tǒng)的組成

對(duì)象1對(duì)象2對(duì)象3對(duì)象4圖中箭頭表示對(duì)象之間的消息傳遞對(duì)象作為程序模塊面向?qū)ο蟮能浖到y(tǒng)中每一個(gè)模塊都是高度獨(dú)立的對(duì)象,而對(duì)象是比功能模塊粒度更大的模塊。對(duì)象是由數(shù)據(jù)和對(duì)數(shù)據(jù)的操作(代碼)形成的一個(gè)整體。面向?qū)ο蟪绦蛟O(shè)計(jì)采用封裝的辦法,使對(duì)象的內(nèi)部實(shí)現(xiàn)與外界隔離,實(shí)現(xiàn)了信息隱藏,從而提供了更理想的模塊化機(jī)制,顯著地減少了程序模塊間的相互干擾和依賴性。

數(shù)據(jù)抽象技術(shù)

將數(shù)據(jù)和對(duì)數(shù)據(jù)的操作封裝在一起,作為一個(gè)相互依存、不可分割的整體——對(duì)象來(lái)處理,它采用數(shù)據(jù)抽象和信息隱藏技術(shù)。它將具有相同特征的對(duì)象抽象成一個(gè)新的數(shù)據(jù)類型——類,并且考慮不同對(duì)象之間的聯(lián)系和對(duì)象類的重用性3.4數(shù)據(jù)抽象3.4.1什么是抽象?3.4.2數(shù)據(jù)抽象和抽象數(shù)據(jù)類型抽象性的例子classstudent{ intnumber; char*name; floatscore;public: student(intnumber1,char*name1,floatscore1); ~student(); voidmodify(floatscore1); voidprint();};抽象是有選擇地忽略。抽象性(Abstraction)抽象是對(duì)復(fù)雜的現(xiàn)實(shí)世界的簡(jiǎn)明的表示。抽象強(qiáng)調(diào)了我們所關(guān)心的(感興趣)的信息,而將我們不關(guān)心的其他信息忽略。名家之言E.Dijkstra:“設(shè)計(jì)并實(shí)現(xiàn)一個(gè)大規(guī)模的軟件的中心問(wèn)題是怎樣減小復(fù)雜度,一個(gè)途徑就是通過(guò)抽象”。BjarneStroustrup說(shuō):“在C++語(yǔ)言中,我一直在努力提高程序設(shè)計(jì)的抽象層次”。抽象數(shù)據(jù)類型一個(gè)值集和作用在值集上的操作集

C++語(yǔ)言中的一個(gè)類就是一個(gè)抽象數(shù)據(jù)類型每個(gè)抽象數(shù)據(jù)類型自成一個(gè)模塊,模塊的接口和內(nèi)部實(shí)現(xiàn)分離開來(lái),使用模塊的應(yīng)用程序員只需要知道如何使用該模塊,而不必知道模塊內(nèi)部是如何實(shí)現(xiàn)的,也就是說(shuō),可以忽略模塊內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)。

3.5封裝性和信息隱藏所謂封裝(encapsulation),就是包含和隱藏對(duì)象信息,如內(nèi)部數(shù)據(jù)結(jié)構(gòu)和代碼的能力。在面向?qū)ο蟮某绦蛑校ㄟ^(guò)創(chuàng)建對(duì)象將代碼和數(shù)據(jù)捆綁在一起,并且在對(duì)象中包含了所有必需的代碼和數(shù)據(jù)。對(duì)象是支持封裝的元素。一個(gè)程序中的對(duì)象把現(xiàn)實(shí)世界中的實(shí)體的屬性和行為封裝成一個(gè)整體。信息隱藏(informationhiding)

封裝的好處封裝性降低了程序設(shè)計(jì)的復(fù)雜度。

封裝將操作對(duì)象的內(nèi)部復(fù)雜性與應(yīng)用程序的其他部分隔離開來(lái)。應(yīng)用程序員只需要通過(guò)對(duì)象的接口來(lái)操作對(duì)象完成特定的任務(wù),而不需要知道對(duì)象內(nèi)部復(fù)雜的細(xì)節(jié)。

封裝的好處(續(xù))提高了代碼的安全性和可靠性;通過(guò)類實(shí)現(xiàn)封裝,集中和統(tǒng)一了對(duì)類中數(shù)據(jù)成員的所有操作,從而可避免因分散操作造成的錯(cuò)誤。能有效提到程序模塊的獨(dú)立性、可重用性和可維護(hù)性;只要類的接口(即類的共有部分)保持不變,類的結(jié)構(gòu)部分的任何變化(包括數(shù)據(jù)結(jié)構(gòu)和算法)都不會(huì)對(duì)使用該類的源程序有所影響,源程序可以不做任何修改。面向?qū)ο蟪绦蛟O(shè)計(jì)的主要特征抽象性封裝性繼承性多態(tài)性3.6繼承性與軟件重用面向?qū)ο蟪绦蛟O(shè)計(jì)的第二個(gè)主要特征就是繼承性,繼承的目的就是為了重用(reuse)。

繼承,就是在一個(gè)已有的類的基礎(chǔ)上創(chuàng)建一個(gè)新類

,這個(gè)新類獲得了已有類的數(shù)據(jù)和操作代碼,并且新類可以增加新的數(shù)據(jù)和操作代碼。

繼承與派生問(wèn)題舉例派生類的概念在已有類的基礎(chǔ)上新增自己的特性而產(chǎn)生新類的過(guò)程稱為派生。被繼承的已有類稱為基類(或父類)。派生出的新類稱為派生類(或子類)。參見圖3.5類的繼承

繼承與派生的目的繼承的目的:實(shí)現(xiàn)代碼重用。派生的目的:當(dāng)新的問(wèn)題出現(xiàn),原有程序無(wú)法解決(或不能完全解決)時(shí),需要對(duì)原有程序進(jìn)行改造。C++中類的繼承層次自然地表達(dá)了人們分析問(wèn)題時(shí)所用的分類結(jié)構(gòu)。大大改善了軟件系統(tǒng)的可理解性和可維護(hù)性。

繼承的好處(1)繼承性很好地實(shí)現(xiàn)了代碼的重用。(2)能改進(jìn)軟件系統(tǒng)的可維護(hù)性。(3)繼承性使已有的程序庫(kù)具有清晰的層次結(jié)構(gòu)關(guān)系。3.7多態(tài)性廣義多態(tài)性:自然語(yǔ)言中的多態(tài)性;面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)性什么是多態(tài)性?(廣義)polymorphism,“manyforms”:即多種形態(tài)在自然語(yǔ)言中,多態(tài)性即是“一詞多義”;更準(zhǔn)確地說(shuō),多態(tài)性是指相同的動(dòng)詞作用到不同類型的對(duì)象上,例如:

駕駛摩托車 駕駛汽車 駕駛飛機(jī) 駕駛輪船駕駛宇宙飛船什么是多態(tài)性?(OOP)當(dāng)不同對(duì)象接受到相同的消息產(chǎn)生不同的動(dòng)作,這種性質(zhì)稱為多態(tài)性。通俗地說(shuō),多態(tài)性是指用一個(gè)名字定義不同的函數(shù),這些函數(shù)執(zhí)行不同但又類似的操作,即用同樣的接口訪問(wèn)功能不同的函數(shù),從而實(shí)現(xiàn)“一個(gè)接口,多種方法”。多態(tài)性的例子在C語(yǔ)言中,由于不支持多態(tài),求絕對(duì)值的動(dòng)作要求三個(gè)不同的函數(shù)名字:

abs(),labs(),fabs()分別用來(lái)求整數(shù),長(zhǎng)整數(shù)、浮點(diǎn)數(shù)的絕對(duì)值。在C++語(yǔ)言中,由于支持多態(tài),求絕對(duì)值的動(dòng)作可以只用一個(gè)函數(shù)名:abs()應(yīng)用多態(tài)性的好處多態(tài)應(yīng)用于OOP的目的是允許用一個(gè)名字來(lái)指定動(dòng)作的一般類(即邏輯上相似的動(dòng)作)。從而帶來(lái)以下的好處:提高了處理問(wèn)題的抽象級(jí)別;降低了程序設(shè)計(jì)時(shí)的復(fù)雜性;增強(qiáng)了軟件的靈活性。面向?qū)ο蟪绦蛟O(shè)計(jì)的優(yōu)越性重用性:有利于軟件生產(chǎn)率的提高;符合人類的自然思維習(xí)慣,能夠自然地描述現(xiàn)實(shí)世界的實(shí)體和問(wèn)題:有利于控制軟件的復(fù)雜性;更好的模塊化,便于多人分工和合作開發(fā)軟件;編寫的代碼有更好的可維護(hù)性;3.8面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言3.8.1對(duì)象程序設(shè)計(jì)語(yǔ)言的發(fā)展概況3.8.2幾種典型的面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言幾種典型的OOPLSmalltalkC++JavaC#

3.9面向?qū)ο蟮能浖こ堂嫦驅(qū)ο蟮姆治觯∣bject-OrientedAnalysis,簡(jiǎn)稱OOA)面向?qū)ο蟮脑O(shè)計(jì)(Object-OrientedDesign,簡(jiǎn)稱OOD)面向?qū)ο蟮木幊蹋∣bject-OrientedProgramming,簡(jiǎn)稱OOP)面向?qū)ο蟮臏y(cè)試(Object-OrientedTest,簡(jiǎn)稱OOT)面向?qū)ο蟮能浖S護(hù)(Object-OrientedSoftwareMaintain,簡(jiǎn)稱OOSM)《C++面向?qū)ο蟪绦蛟O(shè)計(jì)》教學(xué)內(nèi)容

第1章 C++概述第2章 類和對(duì)象第3章面向?qū)ο蟪绦蛟O(shè)計(jì)概述第4章進(jìn)一步學(xué)習(xí)類和對(duì)象第5章堆與復(fù)制構(gòu)造函數(shù)第6章繼承性:派生類第7章運(yùn)算符重載第8章 虛函數(shù)和多態(tài)性第9章 模板第10章類庫(kù)和C++的標(biāo)準(zhǔn)模板庫(kù)STL第11章輸入輸出流第12章異常處理第4章進(jìn)一步學(xué)習(xí)類和對(duì)象4.1對(duì)象數(shù)組4.2指向?qū)ο蟮闹羔?.3this指針4.4對(duì)象的賦值4.5對(duì)象作為函數(shù)參數(shù)4.6從函數(shù)返回對(duì)象4.7類的靜態(tài)成員4.8類的友元4.1對(duì)象數(shù)組(Objectarrays)定義: 類名數(shù)組名[元素個(gè)數(shù)];例如:StudentaSA[10];//一個(gè)學(xué)生類對(duì)象數(shù)組通過(guò)下標(biāo)訪問(wèn)方法: 數(shù)組名[下標(biāo)].成員名;例如:aSA[j].print();對(duì)象數(shù)組初始化數(shù)組中每一個(gè)元素對(duì)象被創(chuàng)建時(shí),系統(tǒng)都會(huì)調(diào)用構(gòu)造函數(shù)類初始化該對(duì)象。通過(guò)初始化列表賦值。例:

LocationA[2]={Location(1,2),Location(3,4)};如果沒(méi)有為數(shù)組元素指定顯式初始值,數(shù)組元素使用缺省值初始化(調(diào)用缺省構(gòu)造函數(shù))。當(dāng)數(shù)組中每一個(gè)對(duì)象被刪除時(shí),系統(tǒng)都要調(diào)用一次析構(gòu)函數(shù)。數(shù)組元素所屬類的構(gòu)造函數(shù)沒(méi)有自定義構(gòu)造函數(shù)時(shí),則采用缺省構(gòu)造函數(shù)。各元素對(duì)象的初值要求為相同的值時(shí),可以定義出具有缺省形參值的構(gòu)造函數(shù)。各元素對(duì)象的初值要求為不同的值時(shí),需要定義帶形參(無(wú)缺省值)的構(gòu)造函數(shù)。如果需要定義動(dòng)態(tài)數(shù)組,需要一個(gè)無(wú)參構(gòu)造函數(shù)。對(duì)象數(shù)組例子#include<iostream.h>classsamp{inta,b;public:samp(intn,intm){a=n;b=m;}intget_a(){returna;}intget_b(){returnb;}};對(duì)象數(shù)組例子(續(xù))main(){sampob[4][2]={samp(1,2),samp(3,4),samp(5,6),samp(7,8),samp(9,10),samp(11,12),samp(13,14),samp(15,16),};inti;對(duì)象數(shù)組例子(續(xù))

for(i=0;i<4;i++){cout<<ob[i][0].get_a();cout<<ob[i][0].get_b()<<"\n";cout<<ob[i][1].get_a();cout<<ob[i][1].get_b()<<"\n";}cout<<"\n";return0;}4.2指向?qū)ο蟮闹羔樋梢远x指向?qū)ο蟮闹羔槪谶\(yùn)用對(duì)象的指針的時(shí)候,對(duì)象的成員將用箭頭運(yùn)算符(→)而不是點(diǎn)運(yùn)算符(.)引用。對(duì)象的指針?biāo)惴ㄅc其它數(shù)據(jù)類型的指針?biāo)惴ㄏ嗤核慌c對(duì)象相聯(lián)系的處理。例如:當(dāng)對(duì)象指針增加的時(shí)候,它指向下一個(gè)對(duì)象;當(dāng)對(duì)象指針減少的時(shí)候,它指向前一個(gè)對(duì)象。對(duì)象指針的用法

intmain(){

Circlec1(3),*pc;//pc為指向圓形Circle類對(duì)象的指針

pc=&c1; //將對(duì)象c1的地址賦給對(duì)象指針pc,使其指向圓形對(duì)象c1

cout<<c1.GetArea()<<endl; //通過(guò)對(duì)象名訪問(wèn)對(duì)象的方法

cout<<pc->GetArea()<<endl;//通過(guò)對(duì)象指針訪問(wèn)對(duì)象的方法

return0;}對(duì)象指針與對(duì)象數(shù)組#include"student.h"intmain(){… Student*sp=aSA; //給指針賦初值

for(inti=0;i<4;i++,sp++)sp->print();//指針加1后,指向下一個(gè)對(duì)象

sp=sp-3; //指針減3后,指針向前移動(dòng)三個(gè)對(duì)象

sp->modify(87); sp->print(); return0;}4.3this指針對(duì)象是由數(shù)據(jù)和操作構(gòu)成的一個(gè)整體,即使同一類的不同對(duì)象的操作也是相互獨(dú)立的,各占不同的內(nèi)存空間。但是,在C++實(shí)現(xiàn)中,這種處理方案太浪費(fèi)內(nèi)存空間。同類的對(duì)象能否共享該類成員函數(shù)的同一個(gè)實(shí)例呢?myBirthday.set(31,12,1997);nationalDay.set(1.10,1949);voidDate::Set(intD,intM,inty){day=D;month=M;year=Y;}那么,此時(shí)計(jì)算機(jī)怎么能區(qū)分該函數(shù)是作用在哪個(gè)對(duì)象上呢?解決方案C++在編譯時(shí),自動(dòng)在每個(gè)成員函數(shù)中的第一個(gè)參數(shù)位置增加:

X*constthis;

當(dāng)對(duì)象調(diào)用該函數(shù)時(shí),編譯器自動(dòng)將該對(duì)象的指針作為實(shí)參傳遞給相應(yīng)的函數(shù),這樣就可解決上述問(wèn)題:voidDate::Set(Date*constthis,intD,intM,intY){this->day=D;this->month=M;this->year=Y;}

注:程序員不能將this指針的說(shuō)明寫在函數(shù)中C的結(jié)構(gòu)體struct與C++的struct的比較C語(yǔ)言的結(jié)構(gòu)體中數(shù)據(jù)與操作是分離的

在C++語(yǔ)言中將數(shù)據(jù)與操作封裝在一個(gè)結(jié)構(gòu)體中

structStudent{ intnumber; charname[15]; floatscore;};數(shù)據(jù)成員structStudent{intnumber;charname[15];floatscore;voiddisplay(Student*this)//函數(shù)成員{ cout<<”number:”<<this->number; cout<<”name:”<<this->name; cout<<”score:”<<this->score<<endl;}};/*獨(dú)立函數(shù)display*/voiddisplay(Student*stu){ printf(”number:%d”,stu->number); printf(”name:%s”,stu->name); printf(”score:%f\n”,stu->score);}數(shù)據(jù)成員this指針this指針是由C++編譯器自動(dòng)產(chǎn)生而使用的一個(gè)隱含指針,類成員函數(shù)使用該指針來(lái)存取對(duì)象的數(shù)據(jù)成員。

定義同一類的多個(gè)對(duì)象時(shí),每個(gè)對(duì)象擁有自己的數(shù)據(jù)成員但它們共用一份成員函數(shù),當(dāng)成員函數(shù)存取對(duì)象的數(shù)據(jù)時(shí)它們使用this指針,通過(guò)this指針指向不同對(duì)象來(lái)決定使用哪一個(gè)對(duì)象的數(shù)據(jù)成員。this指針是如何在“幕后”工作?例如complex類中的init函數(shù):voidinit(doubler,doublei){real=r;image=i;}C++編譯器在編譯這個(gè)函數(shù)時(shí)自動(dòng)插入this指針:voidinit(complex*this,doubler,doublei){this->real=r;this->image=i;}this指針的顯式使用this指針是系統(tǒng)的一個(gè)內(nèi)部指針,通常以隱式方式使用,但也可以為程序員所使用,例如,當(dāng)運(yùn)算符重載和建立鏈表時(shí)this指針顯得十分重要。參見雙向鏈表This指針的顯式用法顯式地使用this指針,還可以使C++的編譯器將同名的參數(shù)與數(shù)據(jù)成員區(qū)分開來(lái):voidDate::Set(intday,intmonth,intyear){this->day=day;this->month=month;this->year=year;}4.4對(duì)象的賦值如果兩個(gè)對(duì)象屬于同一種類型,那么我們可以將其中的一個(gè)對(duì)象的值(屬性值)賦給另一個(gè)對(duì)象。在默認(rèn)情況下,當(dāng)將一個(gè)對(duì)象賦值給另一個(gè)對(duì)象時(shí),第一個(gè)對(duì)象的數(shù)據(jù)將被按位復(fù)制到第二個(gè)對(duì)象中。對(duì)象賦值的例子【例4.4】

intmain(){Rectanglerect1(10,20),rect2(0,0);

cout<<"rect1beforeassignment:\n";rect1.show_Rect();cout<<"rect2beforeassignment:\n";rect2.show_Rect();cout<<'\n';

rect2=rect1;//將矩形對(duì)象rect1賦值給矩形對(duì)象rect2

cout<<"rect1afterassignment:\n";rect1.show_Rect();cout<<"rect2afterassignment:\n";rect2.show_Rect();

return0;}C++語(yǔ)言系統(tǒng)為Rectangle類自動(dòng)提供的賦值運(yùn)算符=

4.5對(duì)象作為函數(shù)參數(shù)在C++中,對(duì)象也可以象其它類型的數(shù)據(jù)一樣,作為函數(shù)的參數(shù)。對(duì)象作為函數(shù)的參數(shù)時(shí),實(shí)際參數(shù)與形式參數(shù)的傳遞方式也有兩種:傳送數(shù)值(傳值調(diào)用CallbyValue)傳送地址(傳址調(diào)用CallbyReference)傳值調(diào)用CallbyValue傳值調(diào)用時(shí),傳送的是作為實(shí)際參數(shù)的對(duì)象的拷貝而不是實(shí)際對(duì)象本身。因此函數(shù)中對(duì)對(duì)象的任何修改均不影響作為實(shí)際參數(shù)的對(duì)象本身。創(chuàng)建形式參數(shù)對(duì)象時(shí),是通過(guò)類的復(fù)制構(gòu)造函數(shù)完成的。傳值調(diào)用例子【例4.5】

classSquare{intside;public:voidset(intx){side=x;}voidout(){cout<<side<<"\n";}};voidf(Squarex)//采用傳值方式將實(shí)際對(duì)象傳送給臨時(shí)對(duì)象x{x.out();//輸出正方形Square類對(duì)象x的邊長(zhǎng)為10

x.set(100);//這僅僅修改了臨時(shí)對(duì)象x的邊長(zhǎng)

x.out();//輸出正方形Square類對(duì)象x的邊長(zhǎng)為100}傳值調(diào)用例子(續(xù))intmain(){Squares;

s.set(10);f(s); s.out();//輸出正方形對(duì)象s的邊長(zhǎng)仍然為10,邊長(zhǎng)沒(méi)有改變

return0;}對(duì)象s以傳值方式傳送給臨時(shí)對(duì)象傳址調(diào)用CallbyReference傳址調(diào)用時(shí),傳遞的是作為實(shí)際參數(shù)的對(duì)象的地址;在函數(shù)中對(duì)作為形式參數(shù)的對(duì)象的修改實(shí)際上就是對(duì)作為實(shí)際參數(shù)的對(duì)象的修改。傳址調(diào)用時(shí),即可以使用指針,也可以使用引用。傳址調(diào)用例子【例4.6】

classSquare{intside;public:voidset(intx){side=x;}voidout(){cout<<side<<"\n";}};

voidf(Square&x)//對(duì)象的引用作為函數(shù)的參數(shù){

x.out();//輸出正方形對(duì)象x的邊長(zhǎng)為10

x.set(100);//這實(shí)際上就是對(duì)作為實(shí)際參數(shù)的對(duì)象s的修改

x.out();//輸出正方形對(duì)象x的邊長(zhǎng)為100}傳址調(diào)用例子(續(xù))intmain(){Squares;

s.set(10);f(s); //傳送對(duì)象s的引用給x,x和s代表同一個(gè)對(duì)象

s.out();//輸出正方形對(duì)象s的邊長(zhǎng)為100,邊長(zhǎng)改變了

return0;}傳送對(duì)象s的地址4.6從函數(shù)返回對(duì)象函數(shù)也可以返回對(duì)象。要從函數(shù)返回一個(gè)對(duì)象,首先必須將函數(shù)的返回類型聲明為一個(gè)類類型。在函數(shù)結(jié)束之前用return語(yǔ)句返回該類的一個(gè)對(duì)象。

【例4.8】函數(shù)返回對(duì)象

myStringinput()//函數(shù)的返回類型為myString{charinstr[80];myStringstr;

cout<<"Enterastring:";cin>>instr;

str.set(instr);

returnstr;//返回一個(gè)myString類型的對(duì)象}【例4.8】函數(shù)返回對(duì)象(續(xù))intmain(){myStringob;

//將返回的對(duì)象復(fù)制給對(duì)象obob=input();ob.print();

return0;}4.7類的靜態(tài)成員

(staticmembers)一、靜態(tài)數(shù)據(jù)成員二、靜態(tài)成員函數(shù)4.7.1靜態(tài)數(shù)據(jù)成員聲明類的靜態(tài)數(shù)據(jù)成員的方式是在變量聲明的前面加static關(guān)鍵字。classPeople{private:

staticintcount;intage;char*name;public:

staticinttotalAge;people(intold,char*string);…

};靜態(tài)數(shù)據(jù)成員的初始化#include<iostream.h>staticintPeople::count=0;staticintPeople::totalAge=0;main(){Peoplemember(32,“Smith”)’Peoplemember(18,“John”);…}注意:在用People類生成任何對(duì)象之前,必須對(duì)其中的靜態(tài)數(shù)據(jù)成員單獨(dú)初始化。靜態(tài)成員的訪問(wèn)當(dāng)通過(guò)對(duì)象訪問(wèn)靜態(tài)成員時(shí),其訪問(wèn)規(guī)則與一般成員的相同,即只能訪問(wèn)公有成員。例如:

member1.totalage=100;//正確。

member1.count=12l//錯(cuò)。注意:靜態(tài)數(shù)據(jù)成員要在生成該類的任何實(shí)例對(duì)象之前初始化,并且不能用構(gòu)造函數(shù)初始化。

靜態(tài)成員變量的應(yīng)用靜態(tài)成員變量的最一般的作用就是對(duì)一些共享資源提供存取控制。例如,可能創(chuàng)建幾個(gè)對(duì)象,每個(gè)對(duì)象要對(duì)某個(gè)磁盤文件進(jìn)行寫操作,但顯然在同一時(shí)間里只允許一個(gè)對(duì)象寫文件。在這種情況下,程序員可能希望說(shuō)明一個(gè)靜態(tài)變量指出文件何時(shí)在使用,何時(shí)處于空閑狀態(tài)。然后,每個(gè)對(duì)象在寫文件之前詢問(wèn)這個(gè)對(duì)象。請(qǐng)看下面的例子:靜態(tài)成員變量的例子#include"iostream.h"classcl{

staticintresource;public: intget_resource(); voidfree_resource(){resource=0;}};intcl::get_resource(){ if(resource)return0;//resourcealreadyinuse else{resource=1; return1;//resourceallocatedtothisobject }}靜態(tài)成員變量的例子(續(xù))intcl::resource=0;main(){ clob1,ob2; if(ob1.get_resource()) cout<<"ob1hasresource\n"; if(!ob2.get_resource()) cout<<"ob2deniedbyresource\n"; ob1.free_resource();//letsomeoneelseuseit. if(ob2.get_resource()) cout<<"ob2canuseresourcenow.\n"; return0;}在生成該類對(duì)象之前初始化替代全局變量靜態(tài)數(shù)據(jù)成員屬于整個(gè)類。不論定義多少個(gè)該類的對(duì)象,靜態(tài)成員只有一個(gè)拷貝。該類所有的對(duì)象都可以通過(guò)這個(gè)成員實(shí)現(xiàn)數(shù)據(jù)共享。通過(guò)使用靜態(tài)成員變量,實(shí)際上可以完全消滅全局變量。按照軟件工程的原則,應(yīng)該盡可能少地使用全局變量。4.7.2靜態(tài)成員函數(shù)

在類中只使用靜態(tài)數(shù)據(jù)成員的函數(shù)可以定義為靜態(tài)成員函數(shù)。靜態(tài)成員函數(shù)的定義方法是在原函數(shù)定義前加static關(guān)鍵字。對(duì)靜態(tài)成員函數(shù)的引用與靜態(tài)數(shù)據(jù)成員一樣是利用所屬的類加范圍運(yùn)算符。靜態(tài)成員函數(shù)的聲明在C++中,用static把一個(gè)成員函數(shù)聲明成一個(gè)靜態(tài)的成員函數(shù)。例如:【例4.11】

classStudent{… public:

staticvoidinit(){

Student::count=0; Student::sum=0; }

staticfloataverage();//靜態(tài)成員函數(shù)的聲明};靜態(tài)成員函數(shù)的聲明和定義靜態(tài)成員函數(shù)的主要作用floatStudent::average(){

cout<<"sumis"<<sum<<"\tcountis"<<count<<endl; cout<<"averageis"<<sum/count<<endl; returnsum/count;}//靜態(tài)成員函數(shù)的定義主要用來(lái)操作靜態(tài)數(shù)據(jù)成員靜態(tài)成員函數(shù)的訪問(wèn)靜態(tài)成員函數(shù)的訪問(wèn)通常采用如下形式:

X::靜態(tài)成員函數(shù)(X是類名)注意:構(gòu)造函數(shù)和析構(gòu)函數(shù)不能是靜態(tài)的。靜態(tài)函數(shù)沒(méi)有this指針,只能訪問(wèn)靜態(tài)的數(shù)據(jù)成員,要想訪問(wèn)非靜態(tài)成員,必須將this指針顯式地傳給它。

voidX::Fun(intiv,X*p){member1=iv;//錯(cuò),member1是非靜態(tài)成員

p->member1=iv;//正確。

member2=iv;//正確。}4.8類的友元(friends)4.8.1友元函數(shù)(朋友函數(shù)friendsfunction)4.8.2友元類4.8.1友元函數(shù)1.一個(gè)類的友元函數(shù)是在該類中說(shuō)明的一個(gè)非成員函數(shù),但允許訪問(wèn)該類對(duì)象的所有成員。2.將關(guān)鍵字friend放在函數(shù)名的前面就將該函數(shù)說(shuō)明為友元函數(shù)。3.友元函數(shù)的說(shuō)明可以出現(xiàn)在類的私有部分或公有部分。程序員應(yīng)將友元看作類的接口的一部分。友元函數(shù)舉例#include<iostream.h>#include<math.h>classPoint{public:Point(doublexi,doubleyi){X=xi;Y=yi;}doubleGetX(){returnX;}doubleGetY(){returnY;}

frienddoubleDistance(Point&a,Point&b);private:doubleX,Y;};雖然友員函數(shù)在類內(nèi)定義,但它不屬于類的成員函數(shù),所以沒(méi)有this指針。因此必須在友元函數(shù)的參數(shù)表中顯示地指出要訪問(wèn)的對(duì)象。

友元函數(shù)舉例(續(xù))doubleDistance(Point&a,Point&b){doubledx=a.X-b.X;doubledy=a.Y-b.Y;returnsqrt(dx*dx+dy*dy);}intmain(){Pointp1(3.0,5.0),p2(4.0,6.0);doubled=Distance(p1,p2);cout<<"Thedistanceis"<<d<<endl;return0;}訪問(wèn)對(duì)象中的成員必須通過(guò)對(duì)象名為什么引入友元?

1. 為了提高程序的效率;友元可以直接訪問(wèn)對(duì)象的私有成員,因而節(jié)省調(diào)用成員函數(shù)的開銷。2. 類的使用者可以根據(jù)需要,通過(guò)使用友元來(lái)增加類的接口。3. 支持運(yùn)算符重載。(在第三章中介紹)4.如果需要一個(gè)函數(shù)同時(shí)訪問(wèn)多個(gè)類,則它可以定義為多個(gè)類的友員函數(shù)。例如實(shí)現(xiàn)矩陣類對(duì)象和向量類對(duì)象相乘的函數(shù)矩陣類對(duì)象和向量類對(duì)象相乘的例子classMatrix;classVector{ floatv[4]; //... friendVectoroperator*(constMatrix&,constVector&);};classMatrix{ Vectorv[4]; //... friendVectoroperator*(constMatrix&,constVector&);};矩陣對(duì)象和向量對(duì)象相乘的例子(續(xù))Vectoroperator*(constMatrix&m,constVector&v){ Vectorr; for(inti=0;i<4;i++){//r[i]=m[i]*v; r.v[i]=0; for(intj=0;j<4;j++)r.v[i]+=m.v[i].v[j]*v.v[j]; } returnr;}特別注意使用友元破壞了封裝和數(shù)據(jù)隱藏,導(dǎo)致程序的可維護(hù)性差。因此使用友元時(shí)要慎重地權(quán)衡得失。

4.8.2友元類若一個(gè)類為另一個(gè)類的友元,則此類的所有成員都能訪問(wèn)對(duì)方類的私有成員。定義語(yǔ)法:將友元類名在另一個(gè)類中使用friend修飾說(shuō)明。友元類舉例classA{friendclassB;public:voidDisplay(){cout<<x<<endl;}private:intx;}classB{public:voidSet(inti);voidDisplay();private:

Aa;};友元類舉例(續(xù))voidB::Set(inti){

a.x=i;}voidB::Display(){a.Display();}友員類的成員函數(shù)可以象友員函數(shù)一樣訪問(wèn)該類的所有成員。

【例4.14】友元類的應(yīng)用classnode{ //節(jié)點(diǎn)類//public: node(intd,node*n=0) { data=d; next=n; }

friendclasslist;

//鏈表類list是節(jié)點(diǎn)類node的友元類private: intdata; node*next;};【例4.14】友元類的應(yīng)用(續(xù)1)classlist{//鏈表類public: list() { head=tail=0; node_count=0; } ~list()//釋放鏈表全部

溫馨提示

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

評(píng)論

0/150

提交評(píng)論