《CC++語言程序設(shè)計(jì)案例教程》課件-第9章類 與 對(duì) 象_第1頁
《CC++語言程序設(shè)計(jì)案例教程》課件-第9章類 與 對(duì) 象_第2頁
《CC++語言程序設(shè)計(jì)案例教程》課件-第9章類 與 對(duì) 象_第3頁
《CC++語言程序設(shè)計(jì)案例教程》課件-第9章類 與 對(duì) 象_第4頁
《CC++語言程序設(shè)計(jì)案例教程》課件-第9章類 與 對(duì) 象_第5頁
已閱讀5頁,還剩98頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1第九章類與對(duì)象

C

語言程序設(shè)計(jì)案例教程12/23/20242隨著計(jì)算機(jī)技術(shù)應(yīng)用的不斷深入,面向過程的程序設(shè)計(jì)的開發(fā)方法已不太適應(yīng)越來越復(fù)雜且高速發(fā)展的信息處理的要求。20世紀(jì)80年代以來,面向?qū)ο蠓椒朔藗鹘y(tǒng)的結(jié)構(gòu)化方法在建立問題系統(tǒng)模型和求解問題時(shí)存在的缺陷,提供了更合理、更有效、更自然的方法,正被廣大的系統(tǒng)分析和設(shè)計(jì)人員認(rèn)識(shí)、接受、應(yīng)用和推廣,實(shí)際上已成為現(xiàn)今軟件系統(tǒng)開發(fā)的主流技術(shù)。C++?是最具代表性的面向?qū)ο蟪绦蛟O(shè)計(jì)語言。C++?是從C發(fā)展而來,它繼承了C語言的優(yōu)點(diǎn),并引入了面向?qū)ο蟮母拍?,是C語言的超集,完全兼容標(biāo)準(zhǔn)C;同時(shí)也增加了一些新特性,這些新特性使C++?程序比C程序更簡(jiǎn)潔、更安全。12/23/202439.1C++?對(duì)C的改進(jìn)9.1.1常規(guī)的改進(jìn)1.新增的關(guān)鍵字C++?在C語言關(guān)鍵字的基礎(chǔ)上增加了許多關(guān)鍵字,下面列出幾種常用的關(guān)鍵字:asmcatchclassdeletefriendinlinenamespacenewoperatorprivateprotectedpublictemplatetryusingvirtual在將原來用C語言寫的程序用C++編譯之前,應(yīng)把與上述關(guān)鍵字同名的標(biāo)識(shí)符改名。2.注釋在C語言中,用“/*”及“*/”作為注釋分界符號(hào),C++?除了保留這種注釋方式外,還提供了一種更有效的注釋方式,即用“//”導(dǎo)引出單行注釋。例如:inta;/*定義一個(gè)整型變量*/intA;//定義一個(gè)整型變量這兩條語句是等價(jià)的。C++?的“//…”注釋方式特別適合于注釋內(nèi)容不超過一行的注釋?!?*…*/”被稱為塊注釋,“//…”被稱為行注釋。12/23/202443.類型轉(zhuǎn)換C++?支持兩種不同的類型轉(zhuǎn)換形式:inti=0;longl=(long)i; //C的類型轉(zhuǎn)換longm=long(i); //C++?的新風(fēng)格4.靈活的變量聲明在C語言中,局部變量說明必須置于可執(zhí)行代碼段之前,不允許將局部變量說明和可執(zhí)行代碼混合起來。但在C++?中,允許在代碼塊的任何地方說明局部變量,也就是說,變量可以放在任何語句位置,不必非放在程序段的開始處。例如:voidf(){inti;i=1;intj;j=2;//…}這樣,可以隨用隨定義,這是C++?封裝的要求,易讀性好,而且避免了變量在遠(yuǎn)離使用處的地方聲明,易引起的混淆或?qū)е洛e(cuò)誤的問題。12/23/202455.?const在C語言中,使用#define來定義常量,例如:#defineSIZE100C++?提供了一種更靈活、更安全的方式來定義變量,即使用類型限定符const來表示常量。所以,C++?中的常量可以是有類型的,程序員不必再用?#define創(chuàng)建無類型常量。例如:constintsize=100;聲明成const的變量,實(shí)際是常量,它有地址,可以用指針指向這個(gè)值,但在程序中是不可修改的。使用?#define有時(shí)是不安全的,如下例所示。12/23/20246例9.1#define的不安全性。#include<iostream.h>voidmain(){intx=1;#defineWx+x#defineYW-Wcout<<"Yis"<<Y<<endl;}初看程序,似乎應(yīng)打印出:Yis0但是實(shí)際的輸出結(jié)果是:Yis2其原因是C++?把語句“cout<<"Yis"<<Y<<endl;”解釋成“cout<<"Yis"<<x+x-x+x<<endl;”,如果程序中用const取代了兩個(gè)#define,將不會(huì)引起這個(gè)問題。12/23/20247例9.2使用const消除#define的不安全性。#include<iostream.h>voidmain(){intx=1;constW=x+xconstY=W-Wcout<<"Yis"<<Y<<endl;}輸出:Yis0另外,在ANSIC中,用const定義的常量是全局常量,而C++?中const定義的常量根據(jù)其定義位置來決定其是局部的還是全局的。12/23/202486.structC++?的struct后的標(biāo)識(shí)符可看作是類型名,所以定義某個(gè)變量比C中更加直觀。例如,在C語言中:structpoint{intx;inty;};structpointp;而在C++?中:structpoint{intx;inty;};pointp;這里不必再寫struct。對(duì)于union,也可以照此使用。為了保持兼容性,C++?仍然接受老用法。在后面會(huì)看到,C++?的類就是對(duì)C中的struct的擴(kuò)充。12/23/202497.作用域分辨運(yùn)算符“::”“::”是作用域分辨運(yùn)算符,它用于訪問在當(dāng)前作用域中被隱藏的數(shù)據(jù)項(xiàng)。如果有兩個(gè)同名變量,一個(gè)是全局的,另一個(gè)是局部的,那么局部變量在其作用域內(nèi)具有較高的優(yōu)先權(quán)。12/23/202410例9.3局部變量在其作用域內(nèi)具有較高的優(yōu)先權(quán),會(huì)屏蔽同名的全局變量。#include<iostream.h>intX=1;//全局變量Xintmain(){intX;X=2;//局部變量Xcout<<"Xis"<<X<<endl;}程序運(yùn)行結(jié)果如下:Xis2如果希望在局部變量的作用域內(nèi)使用同名的全局變量,可以在該變量前加上“::”,此時(shí)“::X”代表全局變量。12/23/202411例9.4使用域作用運(yùn)算符。#include<iostream.h>intX;//全局變量Xintmain(){intX;X=2;//局部變量X::X=1;//全局變量Xcout<<"localXis"<<X<<endl;cout<<"globalXis"<<::X<<endl;}程序運(yùn)行結(jié)果如下:localXis2globalXis112/23/202412注意:作用域分辨運(yùn)算符“::”只能用來訪問全局變量,不能用于訪問一個(gè)在語句塊外聲明的同名局部變量。例如,下面的代碼是錯(cuò)誤的:voidmain(){intX=10;//語句塊外的局部變量

{intX=25;//語句塊內(nèi)的局部變量

::X=30;//編譯報(bào)錯(cuò):X不是全局變量

…}}12/23/2024139.1.2C++的動(dòng)態(tài)內(nèi)存分配C程序中,動(dòng)態(tài)內(nèi)存分配是通過調(diào)用malloc()和free()等庫函數(shù)來實(shí)現(xiàn)的,而C++給出了使用new和delete運(yùn)算符進(jìn)行動(dòng)態(tài)內(nèi)存分配的新方法。運(yùn)算符new用于內(nèi)存分配的使用形式為:p=newtype;其中,type是一個(gè)數(shù)據(jù)類型名,p是指向該數(shù)據(jù)類型的指針。new從內(nèi)存中為程序分配一塊sizeof(type)字節(jié)大小的內(nèi)存,該塊內(nèi)存的首地址存于指針p中。運(yùn)算符delete用于釋放new分配的存儲(chǔ)空間,它的使用形式為:deletep;其中,p必須是一個(gè)指針,保存著new分配的內(nèi)存的首地址,使用delete來釋放指針內(nèi)存。以下是C++程序中用新方法實(shí)現(xiàn)動(dòng)態(tài)內(nèi)存分配的例子。12/23/202414例9.5用new實(shí)現(xiàn)動(dòng)態(tài)內(nèi)存分配。#include<iostream.h>voidmain(){int*X=newint;//為指針X分配存儲(chǔ)空間*X=10;cout<<*X;deleteX;//釋放X指向的存儲(chǔ)空間}使用傳統(tǒng)的C程序?qū)崿F(xiàn)是這樣的:12/23/202415例9.6用malloc實(shí)現(xiàn)內(nèi)存分配。#include<stdio.h>#include<malloc.h>voidmain(){int*X;X=(int*)malloc(sizeof(int));*X=10;printf("%d",*X);free(X);}12/23/202416下面我們?cè)賹?duì)new和delete的使用作幾點(diǎn)說明:(1)使用new可以為數(shù)組動(dòng)態(tài)分配存儲(chǔ)空間,這時(shí)需要在類型名后綴上數(shù)組大小。例如:int*p=newint[10];這時(shí)new為具有10個(gè)元素的整型數(shù)組分配了內(nèi)存空間,并將首地址賦給了指針p。需要注意的是,使用new給多維數(shù)組分配空間時(shí),必須提供所有維的大小。例如:int*p=newint[2][3][4];其中,第一維的界值可以是任何合法的整形表達(dá)式。例如:intX=3;int*p=newint[X][3][4];(2)?new可以在為簡(jiǎn)單變量分配內(nèi)存的同時(shí),進(jìn)行初始化。例如:int*p=newint(100);new分配了一個(gè)整型內(nèi)存空間,并賦初始值100。但是,new不能對(duì)動(dòng)態(tài)分配的數(shù)組存儲(chǔ)區(qū)進(jìn)行初始化。(3)釋放動(dòng)態(tài)分配的數(shù)組存儲(chǔ)區(qū)時(shí),可用如下的delete格式:delete[]p;(4)使用new動(dòng)態(tài)分配內(nèi)存時(shí),如果分配失敗,即沒有足夠的內(nèi)存空間滿足分配要求,new將返回空指針(NULL)。因此通常要對(duì)內(nèi)存的動(dòng)態(tài)分配是否成功進(jìn)行檢查。12/23/202417例如:intmain(){int*p=newint; //為指針p分配存儲(chǔ)空間

if(!p){cout<<"分配失敗"<<endl;return1;}*p=10;cout<<*p;deletep; //釋放p指向的存儲(chǔ)空間}若動(dòng)態(tài)分配失敗,則程序?qū)@示“分配失敗”。為了避免程序出錯(cuò),建議在動(dòng)態(tài)分配內(nèi)存時(shí)對(duì)是否分配成功進(jìn)行檢查。12/23/2024189.1.3引用前面學(xué)習(xí)了指針的概念,指針就是內(nèi)存單元的地址,它可能是變量的地址,也可能是函數(shù)的入口地址。C++?引入了另外一個(gè)同指針相關(guān)的概念:引用。先看一個(gè)例子。例9.7值傳遞應(yīng)用。#include<iostream.h>voidswap(intx,inty){

inttemp;

temp=x;x=y;y=temp;}intmain(){

inta=2,b=1;

cout<<"a="<<a<<",b="<<b<<endl;

swap(a,b);

cout<<"a="<<a<<",b="<<b<<endl;}12/23/202419讓我們來分析一下這個(gè)例子。首先在內(nèi)存空間為a、b開辟兩個(gè)存儲(chǔ)單元并賦初值,然后調(diào)用swap函數(shù),swap函數(shù)為x、y開辟了存儲(chǔ)空間,并將a、b的值傳遞給x、y。x、y的值互換了,在swap結(jié)束時(shí),x、y的生存周期結(jié)束,存儲(chǔ)空間被收回。所以a、b的值并沒有互換。此時(shí)輸出:a=2,b=1a=2,b=1可以使用指針傳遞的方式解決這個(gè)問題,我們改寫上面的程序。例9.8使用指針(地址)進(jìn)行值傳遞。#include<iostream.h>voidswap(int*x,int*y){

inttemp;

temp=*x; *x=*y;*y=temp;}intmain(){

inta=2,b=1;

cout<<"a="<<a<<",b="<<b<<endl;

swap(&a,&b);

cout<<"a="<<a<<",b="<<b<<endl;}12/23/202420程序首先在內(nèi)存空間為a、b開辟兩個(gè)存儲(chǔ)單元并賦初值,然后調(diào)用swap函數(shù),swap函數(shù)為指針x、y開辟了存儲(chǔ)空間,并將a、b的地址傳遞給x、y。在swap函數(shù)中,對(duì)x、y的間接引用的訪問就是對(duì)a、b的訪問,從而交換了a、b的值。那么C++?中還有沒有更簡(jiǎn)單的方式呢?有,那就是引用。引用是能自動(dòng)進(jìn)行間接引用的一種指針。自動(dòng)間接引用就是不必使用間接引用運(yùn)算符*,就可以得到一個(gè)引用值。我們可以這樣理解,引用就是某一變量(目標(biāo))的一個(gè)別名,兩者占據(jù)同樣的內(nèi)存單元,對(duì)引用的操作與對(duì)變量直接操作完全一樣。12/23/2024211.引用的定義定義引用的關(guān)鍵字是“type&”,它的含義是“type類型的引用”。例如:inta=5;int&b=a;它創(chuàng)建了一個(gè)整型引用,b是a的別名,a和b占用內(nèi)存同一位置。當(dāng)a變化時(shí),b也隨之變化,反之亦然。引用的初始值可以是一個(gè)變量或另一個(gè)引用,以下的定義也正確。inta=5;int&b=a;int&b1=b;12/23/2024222.使用規(guī)則(1)定義引用時(shí),必須立即初始化。inta;int&b; //錯(cuò)誤,沒有初始化b=a;(2)引用不可重新賦值。inta,k;int&b=a;b=&k; //錯(cuò)誤,重新賦值(3)引用不同于普通變量,下面的聲明是非法的:int&b[3]; //不能建立引用數(shù)組int&*P; //不能建立指向引用的指針int&&r; //不能建立指向引用的引用12/23/202423(4)當(dāng)使用&運(yùn)算符取一個(gè)引用的地址時(shí),其值為所引用的變量的地址。intnum=50;int&ref=num;int*p=&ref;則p中保存的是變量num的地址。我們使用引用改寫例9.8。12/23/202424例9.9引用傳遞。#include<iostream.h>voidswap(int&x,int&y){

inttemp;

temp=x;

x=y;

y=temp;}main(){

inta=2,b=1;

cout<<"a="<<a<<",b="<<b<<endl;

swap(a,b);

cout<<"a="<<a<<",b="<<b<<endl;return0;}當(dāng)程序中調(diào)用函數(shù)swap()時(shí),實(shí)參a、b分別初始化引用x和y,所在函數(shù)swap()中,x和y分別引用a和b,對(duì)x和y的訪問就是對(duì)a和b的訪問,所以函數(shù)swap()改變了main()函數(shù)中變量a和b的值。盡管通過引用參數(shù)產(chǎn)生的效果同按地址傳遞是一樣的,但其語法更清楚簡(jiǎn)單。C++?主張用引用傳遞取代地址傳遞的方式,因?yàn)榍罢哒Z法容易且不易出錯(cuò)。12/23/2024259.1.4C++?中的函數(shù)C++?對(duì)傳統(tǒng)的C函數(shù)說明作了一些改進(jìn)。這些改進(jìn)主要是為了滿足面向?qū)ο髾C(jī)制的要求,以及可靠性、易讀性的要求。1.主函數(shù)mainC并無特殊規(guī)定main()函數(shù)的格式,因?yàn)橥ǔ2魂P(guān)心返回何種狀態(tài)給操作系統(tǒng)。然而,C++?卻要求main()函數(shù)匹配下面兩種原型之一:voidmain() //無參數(shù),無返回類型intmain(intargc,char*argv[]) //帶參數(shù),有返回類型,參數(shù)也可以省略如果前面不寫返回類型,那么main()等價(jià)于intmain()。函數(shù)要求具有int返回類型,如例9.9。12/23/2024262.函數(shù)原型函數(shù)原型的概念在前面的章節(jié)已提及,函數(shù)原型實(shí)際上就是對(duì)函數(shù)的頭格式進(jìn)行說明,包含函數(shù)名、參數(shù)及返回值類型。C語言建議編程者為程序中的每一個(gè)函數(shù)建立原型,而C++?要求必須為每一個(gè)函數(shù)建立原型。有了函數(shù)原型編譯程序方能進(jìn)行強(qiáng)類型檢查,從而確保函數(shù)調(diào)用的實(shí)參類型與要求的類型相符。早期的C正是缺乏這種強(qiáng)類型檢查,很容易造成非法參數(shù)值傳遞給函數(shù),因此造成程序運(yùn)行時(shí)不可預(yù)料的錯(cuò)誤。函數(shù)原型的語法形式一般為返回類型函數(shù)名(參數(shù)表);函數(shù)原型是一條語句,它必須以分號(hào)結(jié)束。它由函數(shù)的返回類型、函數(shù)名和參數(shù)表構(gòu)成。參數(shù)表包含所有參數(shù)及它們的類型,參數(shù)之間用逗號(hào)分開。請(qǐng)看下面的例子。12/23/202427例9.10C++?中函數(shù)原型的聲明。#include<iostream.h>voidswap(int&m,int&n);//函數(shù)原型的聲明voidmain(){

inta=5,b=10;

cout<<"a="<<a<<"b="<<b<<endl;

swap(a,b);

cout<<"a="<<a<<"b="<<b<<endl;}voidswap(int&m,int&n){

inttemp;

temp=m; m=n;n=temp;}12/23/202428在程序中,要求一個(gè)函數(shù)的原型出現(xiàn)在該函數(shù)的調(diào)用語句之前。這樣,當(dāng)一個(gè)函數(shù)的定義在后,而對(duì)它的調(diào)用在前時(shí),必須將該函數(shù)的原型放在調(diào)用語句之前;但當(dāng)一個(gè)函數(shù)的定義在前,對(duì)它的調(diào)用在后,一般就不必再單獨(dú)給出它的原型了,如例9.9所示。說明:(1)函數(shù)原型的參數(shù)表中可以不包含參數(shù)的名字,而是包含它們的類型,但函數(shù)定義的函數(shù)說明部分中的參數(shù)必須給出名字,而且不包含結(jié)尾的分號(hào)。例如:voidmax(int,int); //函數(shù)原型的聲明voidmax(intm,intn) //函數(shù)定義的函數(shù)說明部分{

//…}(2)原型說明中沒有指出返回類型的函數(shù)(包括主函數(shù)main),C++?默認(rèn)該函數(shù)的返回類型是int,因此以下的原型說明在C++?中是等價(jià)的:fun(inta);intfun(inta);12/23/2024293.內(nèi)置函數(shù)函數(shù)調(diào)用導(dǎo)致了一定數(shù)量的額外開銷,如參數(shù)壓棧、出棧等。有時(shí)正是這種額外開銷迫使C程序員放棄使用函數(shù)調(diào)用,進(jìn)行代碼復(fù)制以提高效率。C++?的內(nèi)置函數(shù)正好解決這一問題。當(dāng)函數(shù)定義是由inline開頭時(shí),表明此函數(shù)為內(nèi)置函數(shù)。編譯時(shí),使用函數(shù)體中的代碼替代函數(shù)調(diào)用表達(dá)式,從而完成與函數(shù)調(diào)用相同的功能,這樣能加快代碼的執(zhí)行,減少調(diào)用開銷。例如:inlineintsum(inta,intb) //內(nèi)置函數(shù){returna+b;}值得注意的是:內(nèi)置函數(shù)必須在它被調(diào)用之前定義,否則編譯不會(huì)得到預(yù)想的結(jié)果。若內(nèi)置函數(shù)較長(zhǎng),且調(diào)用太頻繁時(shí),程序?qū)⒓娱L(zhǎng)很多。因此,通常只有較短的函數(shù)才定義為內(nèi)置函數(shù),對(duì)于較長(zhǎng)的函數(shù),最好作為一般函數(shù)處理。12/23/2024304.缺省參數(shù)值C++?對(duì)C函數(shù)的重要的改進(jìn)之一就是可以為函數(shù)定義缺省的參數(shù)值。例如:intfunction(intx=2,inty=6);//函數(shù)給出缺省的參數(shù)值x與y的值分別是2和6。當(dāng)進(jìn)行函數(shù)調(diào)用時(shí),編譯器按從左向右順序?qū)?shí)參與形參結(jié)合,若未指定足夠的實(shí)參,則編譯器按順序用函數(shù)原型中的缺省值來補(bǔ)足所缺少的實(shí)參。例如:function(1,2); //x=1,y=2function(1); //x=1,y=6function(); //x=2,y=6一個(gè)C++?函數(shù)可以有多個(gè)缺省參數(shù),并且C++?要求缺省參數(shù)必須連續(xù)的放在函數(shù)參數(shù)表的尾部,也就是說,所有取缺省值的參數(shù)都必須出現(xiàn)在不取缺省值的參數(shù)的右邊。當(dāng)調(diào)用具有多個(gè)缺省參數(shù)時(shí),若某個(gè)參數(shù)省略,則其后的參數(shù)皆應(yīng)省略而采用缺省值。當(dāng)不允許出現(xiàn)某個(gè)參數(shù)省略時(shí),再對(duì)其后的參數(shù)指定參數(shù)值。例如:function(,3) //這種調(diào)用方式是錯(cuò)誤的12/23/2024315.函數(shù)重載在C語言中,函數(shù)名必須是唯一的,也就是說不允許出現(xiàn)同名的函數(shù)。當(dāng)要求編寫求整數(shù)、浮點(diǎn)數(shù)和雙精度浮點(diǎn)數(shù)的立方數(shù)的函數(shù)時(shí),若用C語言來處理,必須編寫三個(gè)函數(shù),這三個(gè)函數(shù)的函數(shù)名不允許同名。例如:Icube(inti); //求整數(shù)的三次方Fcube(floatf); //求浮點(diǎn)數(shù)的三次方Dcube(doublei); //求雙精度浮點(diǎn)數(shù)的三次方當(dāng)使用這些函數(shù)求某個(gè)數(shù)的立方數(shù)時(shí),必須調(diào)用合適的函數(shù),也就是說,用戶必須記住這三個(gè)函數(shù),雖然這三個(gè)函數(shù)的功能是相同的。在C++?中,用戶可以重載函數(shù),只要函數(shù)參數(shù)的類型不同,或者參數(shù)的個(gè)數(shù)不同,兩個(gè)或兩個(gè)以上的函數(shù)可以使用相同的函數(shù)名。一般而言,重載函數(shù)應(yīng)執(zhí)行相同的功能。我們可用函數(shù)重載來重寫上面的三個(gè)函數(shù)。12/23/202432例9.11重載cube函數(shù)。#include<iostream.h>intcube(inti){returni*i*i;}floatcube(floatf){returnf*f*f;}doublecube(doubled){returnd*d*d;}intmain(){inti=123;floatf=4.5;doubled=6.78;cout<<i<<'*'<<i<<'*'<<i<<'='<<cube(i)<<endl;cout<<f<<'*'<<f<<'*'<<f<<'='<<cube(f)<<endl;

cout<<d<<'*'<<d<<'*'<<d<<'='<<cube(d)<<endl;}12/23/202433在main()中三次調(diào)用了cube()函數(shù),實(shí)際上調(diào)用了三個(gè)不同的版本。由系統(tǒng)根據(jù)傳送的參數(shù)類型的不同來決定調(diào)用哪個(gè)重載版本。值得注意的是重載函數(shù)應(yīng)在參數(shù)個(gè)數(shù)或參數(shù)類型上有所不同,否則編譯程序?qū)o法確定調(diào)用哪一個(gè)重載版本,即使返回類型不同,也不能區(qū)分。例如:intfun(intx,inty);floatfun(intx,inty);上面的重載就是錯(cuò)誤的。12/23/2024349.2C++?的輸入與輸出C語言提供了強(qiáng)有力的I/O函數(shù),其功能強(qiáng),靈活性好,是很多語言無法比擬的。但C++?為何還要定義自己的I/O系統(tǒng),而不建議使用C語言原有的函數(shù)呢?在C語言中進(jìn)行I/O操作時(shí),常會(huì)出現(xiàn)以下錯(cuò)誤:inti;floatf;scanf("%f",i);printf("%d",f);這些錯(cuò)誤C語言編譯器是不能檢查出來的,而在C++?中,可以將上面的操作寫成:inti;floatf;cin>>i;cout<<f;12/23/202435cin是標(biāo)準(zhǔn)的輸入流,在程序中用于代表標(biāo)準(zhǔn)輸入設(shè)備,即鍵盤。運(yùn)算符“>>”是輸入運(yùn)算符,表示從標(biāo)準(zhǔn)輸入流(即鍵盤)讀取的數(shù)值傳送給右方指定的變量。運(yùn)算符“>>”允許用戶連續(xù)讀入一連串?dāng)?shù)據(jù),兩個(gè)數(shù)據(jù)間用空格、回車或Tab鍵進(jìn)行分割。例如:cin>>x>>y;cout是標(biāo)準(zhǔn)的輸出流,在程序中用于代表標(biāo)準(zhǔn)輸出設(shè)備,通常指屏幕。運(yùn)算符“<<”是輸出運(yùn)算符,表示將右方變量的值顯示到屏幕上。運(yùn)算符“<<”允許用戶連續(xù)輸出數(shù)據(jù)。例如:cout<<x<<y;這里的變量應(yīng)該是基本數(shù)據(jù)類型,不能是void型。其實(shí),可以在同一程序中混用C語言和C++?語言的I/O操作,繼續(xù)保持C語言的靈活性。因而,在把C語言程序改為C++?語言程序時(shí),并不一定要修改每一個(gè)I/O操作。12/23/2024369.2.1C++?的流類結(jié)構(gòu)C++?語言和C語言的I/O系統(tǒng)都是對(duì)流(tream)進(jìn)行操作。流實(shí)際上就是一個(gè)字節(jié)序列。輸入操作中,字節(jié)從輸入設(shè)備(如鍵盤、磁盤、網(wǎng)絡(luò)連接等)流向內(nèi)存;輸出操作中,字節(jié)從內(nèi)存流向輸出設(shè)備。使用C++?式的I/O的程序必須包含頭文件iostream.h,對(duì)某些流函數(shù)可能還需要其他頭文件,例如進(jìn)行文件I/O時(shí)需要頭文件fstream.h。1.?iostream庫iostream庫中具有streambuf和ios兩個(gè)平行的類,這都是基本的類,分別完成不同的工作。streambuf類提供基本流操作,但不提供格式支持。類ios為格式化I/O提供基本操作。2.標(biāo)準(zhǔn)流iostream.h說明了標(biāo)準(zhǔn)流對(duì)象cin、cout、cerr與clog。cin是標(biāo)準(zhǔn)輸入流,對(duì)應(yīng)于C語言的stdin;cout是標(biāo)準(zhǔn)輸出流,對(duì)應(yīng)于C語言的stdout;cerr是標(biāo)準(zhǔn)出錯(cuò)信息輸出,clog是帶緩沖的標(biāo)準(zhǔn)出錯(cuò)信息輸出。cerr和clog流被連到標(biāo)準(zhǔn)輸出上對(duì)應(yīng)于C語言的stderr。cerr和clog之間的區(qū)別是cerr沒有緩沖,發(fā)送給它的任何輸出立即被執(zhí)行,而clog只有當(dāng)緩沖區(qū)滿時(shí)才有輸出。缺省時(shí),C++?語言標(biāo)準(zhǔn)流被連到控制臺(tái)上。12/23/2024379.2.2格式化I/O

習(xí)慣C語言的程序員,對(duì)printf()等函數(shù)的格式化輸入也一定很熟悉。用C++?語言的方法進(jìn)行格式化I/O有兩種方法:其一是用ios類的成員函數(shù)進(jìn)行格式控制;其二是使用操作子。1.狀態(tài)標(biāo)志字C++?語言可以對(duì)每個(gè)流對(duì)象的輸入輸出進(jìn)行格式控制,以滿足用戶對(duì)輸入輸出格式的需求。輸入輸出格式由一個(gè)longint類型的狀態(tài)標(biāo)志字確定。在ios類中定義了一個(gè)枚舉,它的每個(gè)成員可以分別定義狀態(tài)標(biāo)志字的一個(gè)位,每一位都稱為一個(gè)狀態(tài)標(biāo)志位。這個(gè)枚舉定義如下:12/23/202438enum{skipws=0x0001, //跳過輸入中的空白字符,可以用于輸入

left=0x0002, //輸出數(shù)據(jù)左對(duì)齊,可以用于輸出

right=0x0004, //輸出數(shù)據(jù)右對(duì)齊,可以用于輸出

internal=0x0008, //數(shù)據(jù)符號(hào)左對(duì)齊,數(shù)據(jù)本身右對(duì)齊,可以用于輸出

dec=0x0010, //轉(zhuǎn)換基數(shù)為十進(jìn)制形式,可以用于輸入或輸出

oct=0x0020, //轉(zhuǎn)換基數(shù)為八進(jìn)制形式,可以用于輸入或輸出

hex=0x0040, //轉(zhuǎn)換基數(shù)為十六進(jìn)制形式,可以用于輸入或輸出

showbase=0x0080, //輸出的數(shù)值數(shù)據(jù)前面帶基數(shù)符號(hào)(0或0x),可以用于輸入或輸出

showpoint=0x0100, //浮點(diǎn)數(shù)輸出帶小數(shù)點(diǎn),可以用于輸出

uppercase=0x0200, //用大寫字母輸出十六進(jìn)制數(shù)值,可以用于輸出

showpos=0x0400, //正數(shù)前面帶“+”號(hào),可以用于輸出

scientific=0x0800, //浮點(diǎn)數(shù)輸出采用科學(xué)表示法,可以用于輸出

fixed=0x1000, //浮點(diǎn)數(shù)輸出采用定點(diǎn)數(shù)形式,可以用于輸出

unitbuf=0x2000, //完成操作后立即刷新緩沖區(qū),可以用于輸出

stdio=0x4000, //完成操作后刷新stdout和stderr,可以用于輸出};12/23/2024392.?ios類中用于控制輸入輸出格式的成員函數(shù)在ios類中,定義了幾個(gè)用于控制輸入輸出格式的成員函數(shù),下面分別介紹。(1)設(shè)置狀態(tài)標(biāo)志。將某一狀態(tài)標(biāo)志位置為“1”,可以使用setf()函數(shù),其一般格式為longios::setf(longflags);該函數(shù)設(shè)置參數(shù)flags所指定的標(biāo)志位為1,其他標(biāo)志位保持不變,并返回格式更新前的標(biāo)志。例如,要設(shè)置showbase標(biāo)志,可使用如下語句:stream.setf(ios::showbase); //其中stream是所涉及的流實(shí)際上,還可以一次調(diào)用setf()來同時(shí)設(shè)置多個(gè)標(biāo)志。例如:cout.setf(ios::showpos│ios::scientific); //使用按位或運(yùn)算12/23/202440例9.12設(shè)置狀態(tài)標(biāo)志。#include<iostream.h>intmain(){cout.setf(ios::showpos|ios::scientific);cout<<521<<""<<131.4521<<endl;}輸出結(jié)果為+521+1.314521e+002(2)清除狀態(tài)標(biāo)志。清除標(biāo)志可用unsetf()函數(shù),其原型與setf()類似,使用時(shí)調(diào)用格式與setf相同,將參數(shù)flags所指定的標(biāo)志位為0。(3)取狀態(tài)標(biāo)志。用flags()函數(shù)可得到當(dāng)前標(biāo)志值和設(shè)置新標(biāo)志,分別具有以下兩種格式:longios::flags(void);longios::flags(longflags);前者用于返回當(dāng)前的狀態(tài)標(biāo)志字,后者將狀態(tài)標(biāo)志字設(shè)置為flag,并返回設(shè)置前的狀態(tài)標(biāo)志字。flags()函數(shù)與setf()函數(shù)的差別在于:setf()函數(shù)是在原有的基礎(chǔ)上追加設(shè)定的,而flags()函數(shù)是用新設(shè)定替換以前的狀態(tài)標(biāo)志字。12/23/202441(4)設(shè)置域?qū)?。域?qū)捴饕脕砜刂戚敵觯O(shè)置域?qū)捒梢允褂脀idth()函數(shù),其一般格式為intios::width();intios::width(intlen);前者用來返回當(dāng)前的域?qū)捴担笳哂脕碓O(shè)置域?qū)?,并返回原來的域?qū)?。注意每次輸出都需要重新設(shè)定輸出寬度。(5)設(shè)置顯示的精度。設(shè)置顯示精度的函數(shù)一般格式為intios::precision(intnum);此函數(shù)用來重新設(shè)置浮點(diǎn)數(shù)所需的精度,并返回設(shè)置前的精度。默認(rèn)的顯示精度是6位。如果顯示格式是scientific或fixed,精度指小數(shù)點(diǎn)后的位數(shù);如果不是,精度指整個(gè)數(shù)字的有效位數(shù)。(6)填充字符。填充字符函數(shù)的格式為charios::fill();charios::fill(charch);前者用來返回當(dāng)前的填充字符,后者用ch重新設(shè)置填充字符,并返回設(shè)置前的填充字符。12/23/202442下面舉例說明以上這些函數(shù)的作用。例9.13使用ios類中用于控制輸入輸出格式的成員函數(shù)。#include<iostream.h>main(){cout<<"x_width="<<cout.width()<<endl;cout<<"x_fill="<<cout.fill()<<endl;cout<<"x_precision="<<cout.precision()<<endl;cout<<520<<""<<520.45678<<endl;cout<<"-------------------------"<<endl;cout<<"****x_width=10,x_fill=&,x_precision=4****"<<endl;cout.fill('&');cout.width(10);cout.setf(ios::scientific);cout.precision(4);cout<<520<<""<<520.45678<<endl;cout.setf(ios::left);cout.width(10);cout<<520<<""<<520.45678<<endl;cout<<"x_width="<<cout.width()<<endl;cout<<"x_fill="<<cout.fill()<<endl;cout<<"x_precision="<<cout.precision()<<endl;}程序運(yùn)行結(jié)果如下:x_width=0x_fill=x_precision=6520520.457-------------------------****x_width=10,x_fill=&,x_precision=4****&&&&&&&5205.2046e+002520&&&&&&&5.2046e+002x_width=0x_fill=&x_precision=412/23/202443分析以上的程序運(yùn)行結(jié)果可看出:在缺省情況下,x_width取值為“0”,這個(gè)“0”意味著無域?qū)?,既按?shù)據(jù)自身的寬度打?。粁_fill默認(rèn)值為空格;x_precision默認(rèn)值為6,這是因?yàn)闆]有設(shè)置輸出格式是scientific或fixed,所以520.45678輸出為520.457,整個(gè)數(shù)的有效位數(shù)為6,后面省略的位數(shù)四舍五入;接下來設(shè)置x_width為10,x_fill為“&”x_precision為4,輸出格式為scientific。每次輸出都需要重新設(shè)定輸出寬度。由于輸出格式為scientific,精度設(shè)置為4,指的是小數(shù)點(diǎn)后位數(shù),所以輸出為5.2046e+002。12/23/2024443.用操作子進(jìn)行格式化上面介紹的格式控制每個(gè)函數(shù)的調(diào)用需要寫一條語句,而且不能將它們直接嵌入到輸入輸出語句中去,使用起來不方便,因此可以用操作子來改善上述情況。操作子是一個(gè)對(duì)象,可以直接被插入符或提取符操作??刂坪瘮?shù)可作為參數(shù),直接參與I/O操作。C++?流類庫所定義操作子如下:dec,hex,oct:數(shù)值數(shù)據(jù)采用十進(jìn)制或十六進(jìn)制、八進(jìn)制表示,可用于輸入或輸出。ws:提取空白符,僅用于輸入。endl:插入一個(gè)換行符并刷新輸出流,僅用于輸出。ends:插入空字符,僅用于輸出。flush:刷新與流相關(guān)聯(lián)的緩沖區(qū),僅用于輸出。setbase(intn):設(shè)置數(shù)值轉(zhuǎn)換基數(shù)為n(n的取值為0、8、10、16),0表示使用缺省基數(shù),即以十進(jìn)制形式輸出。resetiosflags(longf):清除參數(shù)所指定的標(biāo)志位,可用于輸入或輸出。setiosflags(longf):設(shè)置參數(shù)所指定的標(biāo)志位,可用于輸入或輸出。setfill(intn):設(shè)置填充字符,缺省為空格,可用于輸入或輸出。setsprecision(intn):設(shè)置浮點(diǎn)數(shù)輸出的有效數(shù)字個(gè)數(shù),可用于輸入或輸出。setw(intn):設(shè)置輸出數(shù)據(jù)項(xiàng)的域?qū)?,可用于輸入或輸出。特別注意:使用操作子必須包含頭文件iomanip.h。12/23/202445例9.14使用操作子進(jìn)行格式化。#include<iostream.h>#include<iomanip.h>main(){cout<<setfill('^')<<setw(10)<<123<<setw(5)<<456<<endl;cout<<123<<setiosflags(ios::scientific)<<setw(15)<<123.456789<<endl;cout<<123<<setw(8)<<hex<<123<<endl;cout<<123<<setw(8)<<oct<<123<<endl;cout<<123<<setw(8)<<dec<<123<<endl;cout<<resetiosflags(ios::scientific)<<setprecision(4)<<123.456789<<endl;cout<<setiosflags(ios::left)<<setfill('*')<<setw(8)<<dec<<123<<endl;cout<<resetiosflags(ios::left)<<setfill('^')<<setw(8)<<dec<<456<<endl;}程序運(yùn)行結(jié)果如下:^^^^^^^123^^456123^^1.234568e+002123^^^^^^7b7b^^^^^173173^^^^^123123.5123*****^^^^^45612/23/202446案例一學(xué)生類設(shè)計(jì)1.問題描述設(shè)計(jì)一個(gè)學(xué)生類,具有姓名、年齡、目前學(xué)習(xí)的時(shí)間等信息,根據(jù)學(xué)制確定學(xué)生上學(xué)年限,畢業(yè)時(shí)打印學(xué)生姓名、年齡、修業(yè)年限等信息。2.問題分析注意類和對(duì)象的定義方法、類成員的訪問權(quán)限設(shè)置方法以及不同訪問權(quán)限成員的訪問方法、構(gòu)造函數(shù)和析構(gòu)函數(shù)的設(shè)計(jì)、內(nèi)聯(lián)函數(shù)使用方法、靜態(tài)成員的使用和初始化、函數(shù)默認(rèn)參數(shù)值的設(shè)定、C++?注釋的使用方法、輸入輸出以及相應(yīng)格式的設(shè)置方法等相關(guān)知識(shí)的掌握。12/23/2024473.?C++?代碼#include<iostream.h>#include<iomanip.h>#include<string.h>classstu{ //class是定義類的關(guān)鍵字,stu是類的名字

private: //訪問權(quán)限設(shè)置,后面的成員為私有,直到下一個(gè)權(quán)限設(shè)置進(jìn)行更改

charname[20]; //學(xué)生姓名

intage; //學(xué)生年齡

staticintstudyyear;//static修飾studyyear后成為靜態(tài)的類成員,為所有對(duì)象共享的數(shù)據(jù), 表示學(xué)習(xí)年數(shù)

staticintstunumber;//靜態(tài)的數(shù)據(jù)成員放在類中,不占用對(duì)象空間,stunumber表示學(xué)生總數(shù)

public: //訪問權(quán)限設(shè)置,后面的成員為公有訪問屬性

inlinestu(char*xingming="",intnianling=6,intxuexinianshu=0)//構(gòu)造函數(shù)在類內(nèi)部定義,是內(nèi)聯(lián)函數(shù),有默認(rèn)參數(shù),inline是定義內(nèi)聯(lián)函數(shù)關(guān)鍵字

{stunumber++;strcpy(name,xingming);age=nianling;studyyear=xuexinianshu;}stu(conststu&x) //復(fù)制構(gòu)造函數(shù)在類內(nèi)部定義

{*this=x;stunumber++;}inline~stu(); //析構(gòu)函數(shù)聲明

voidset(char*xingming,intnianling,intxuexinianshu);//重新設(shè)置對(duì)象成員的函數(shù)

voiddisplay(); //顯示對(duì)象成員的函數(shù)

intgetstudyyear(); //獲取目前的學(xué)習(xí)年數(shù)12/23/202448staticvoidaddstudyyear() //靜態(tài)成員函數(shù),只能訪問靜態(tài)數(shù)據(jù)成員,實(shí)現(xiàn)學(xué)習(xí)時(shí)間增加

{studyyear++;}voidaddage() //成員函數(shù),實(shí)現(xiàn)年齡增加

{age++;}}stuA("張三",18,0); //類stu的封裝,定義stuA是全局對(duì)象inlinestu::~stu() //析構(gòu)函數(shù)在類外定義{stunumber--;cout<<this->name<<"經(jīng)過"<<studyyear<<"年學(xué)習(xí)已經(jīng)畢業(yè)!"<<endl;//cout是輸入流對(duì)象,使用需要頭文件iostream.h,this是函數(shù)隱含的對(duì)象指針參數(shù),指向調(diào)用該函數(shù)的對(duì)象}voidstu::set(char*xingming,intnianling,intxuexinianshu){strcpy(name,xingming);age=nianling;studyyear=xuexinianshu;}voidstu::display(){cout.setf(ios::left);//setf是cout的成員函數(shù),ios::left是操作子,使用操作子需要iomanip.h文件

cout<<setw(10)<<"學(xué)生總數(shù)"<<setw(10)<<"姓名"\<<setw(10)<<"年齡"<<setw(10)<<"學(xué)習(xí)年數(shù)"<<endl;//\為續(xù)行符

cout<<setw(10)<<stunumber<<setw(10)<<name<<setw(10)<<age<<setw(10)<<studyyear<<endl;}intstu::getstudyyear(){returnstudyyear;}intstu::studyyear=0; //靜態(tài)數(shù)據(jù)成員的初始化必須放在類外進(jìn)行intstu::stunumber=0;12/23/202449voidmain(){intx; //動(dòng)態(tài)變量x表示畢業(yè)需要的學(xué)制

stuA.display(); //全局對(duì)象stuA的成員顯示

stustuB("李四",19,0); //stuB是局部動(dòng)態(tài)對(duì)象

stuA.display(); //再次顯示stuA的成員,注意分析成員值變化原因

stuB.display(); stustuC=stu(stuB); //stuC是復(fù)制stuBstuA.display();stuB.display();stuC.display();stuC.set("王五",20,0); //stuC重新設(shè)置

stuC.display();cout<<"對(duì)象占有的空間字節(jié)數(shù):"<<sizeof(stuA)<<endl; //函數(shù)及靜態(tài)數(shù)據(jù)成員在類中存放,不占用對(duì)象所用的空間

cout<<"請(qǐng)輸入畢業(yè)需要學(xué)制年數(shù):";cin>>x; //cin是輸入流對(duì)象

while(stuA.getstudyyear()<x) //學(xué)習(xí)年數(shù)小于學(xué)制

{stuA.addage();stuB.addage();stuC.addage();stu::addstudyyear(); //增加學(xué)習(xí)時(shí)間

//靜態(tài)成員函數(shù)調(diào)用可以不通過對(duì)象來進(jìn)行,也可以通過對(duì)象來調(diào)用

}cout<<"學(xué)習(xí)"<<x<<"年后……"<<endl;stuA.display();stuB.display();stuC.display();}12/23/2024504.程序運(yùn)行結(jié)果學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)1張三180學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)2張三180學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)2李四190學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3張三180學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3李四190學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3李四190學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3王五200對(duì)象占有的空間字節(jié)數(shù):24請(qǐng)輸入畢業(yè)需要學(xué)制年數(shù):4學(xué)習(xí)4年后……學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3張三224學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3李四234學(xué)生總數(shù)姓名年齡學(xué)習(xí)年數(shù)3王五244王五經(jīng)過4年學(xué)習(xí)已經(jīng)畢業(yè)!李四經(jīng)過4年學(xué)習(xí)已經(jīng)畢業(yè)!張三經(jīng)過4年學(xué)習(xí)已經(jīng)畢業(yè)!12/23/2024519.3類與對(duì)象的概念C++?是面向過程和面向?qū)ο蟮恼Z言,既支持面向過程也支持面向?qū)ο缶幊?。C++?又稱為帶類的C語言。類是一組具有相同屬性和行為的對(duì)象的統(tǒng)稱,它為屬于該類的全部對(duì)象提供了統(tǒng)一的抽象描述。對(duì)象是類的實(shí)例。類相當(dāng)于C語言中的數(shù)據(jù)類型,對(duì)象相當(dāng)于變量。類需要程序員進(jìn)行定義,類中除可以定義數(shù)據(jù)成員外,還可以定義對(duì)這些數(shù)據(jù)成員進(jìn)行操作的函數(shù)——成員函數(shù);類的成員也有不同的訪問權(quán)限,這樣就保證了數(shù)據(jù)的私有性。下面,我們將要介紹怎樣定義類及類的成員。12/23/2024529.3.1類的定義類的定義一般形式如下:class類名{[private:]私有的數(shù)據(jù)成員和成員函數(shù)public://外部接口公有的數(shù)據(jù)成員和成員函數(shù)protected:保護(hù)性的數(shù)據(jù)成員和成員函數(shù)};類的定義由頭和體兩個(gè)部分組成。類頭由關(guān)鍵字class開頭,然后是類名,其命名規(guī)則與一般標(biāo)識(shí)符的命名規(guī)則一致,類體包括所有的細(xì)節(jié),并放在一對(duì)花括號(hào)中。類的定義也是一個(gè)語句,所以要有分號(hào)結(jié)尾。類體定義類的成員,它支持兩種類型的成員:(1)數(shù)據(jù)成員:指定了該類對(duì)象的內(nèi)部表示。(2)成員函數(shù):指定該類的操作。12/23/2024539.3.2數(shù)據(jù)成員和成員函數(shù)

(1)類的成員分私有成員、保護(hù)性成員和公有成員。私有成員用private說明,私有成員是默認(rèn)的訪問屬性,private下面的每一行,不論是數(shù)據(jù)成員還是成員函數(shù),都是私有成員。私有成員只能被該類的成員函數(shù)或本類的友元函數(shù)(關(guān)于友元函數(shù)的概念后面介紹)訪問,這是C++?實(shí)現(xiàn)封裝的一種方法,即把特定的成員定義為私有成員,就能嚴(yán)格的控制對(duì)它的訪問,如果緊跟在類名稱的后面聲明私有成員,則關(guān)鍵字private可以省略,因?yàn)槌蓡T默認(rèn)的訪問權(quán)限是私有的,以保護(hù)數(shù)據(jù)的安全性。公有成員用public說明,public下面每一行都是公有成員,公有成員可被類外部的其他函數(shù)訪問,它們是類的對(duì)外接口。保護(hù)性成員用protected說明,protected下面每一行都是保護(hù)性成員,保護(hù)成員不可被類外部的其他函數(shù)訪問,只能被本類的成員函數(shù)和本類的派生類(關(guān)于派生類的概念后面介紹)的成員函數(shù)、本類的友元函數(shù)訪問。類聲明中的private、public、protected關(guān)鍵字可以按任意順序出現(xiàn)任意次。定義類的成員及訪問屬性稱為類的封裝,封裝、繼承、多態(tài)(繼承和多態(tài)的概念后續(xù)章節(jié)介紹)是面向?qū)ο蟮娜齻€(gè)基本特征。(2)成員函數(shù)。成員函數(shù)的定義通常采用兩種方式。第一種方式是在類聲明中只給出成員函數(shù)的原型,而成員函數(shù)體在類的外部定義,如案例一中的display();成員函數(shù)的第二種定義方式是:將成員函數(shù)定義在類的內(nèi)部,即定義為內(nèi)聯(lián)函數(shù)。這種情況又分成兩種:一種直接在類中定義函數(shù),如案例一中的inlinestu(char*xingming="",intnianling=6,intxuexinianshu=0)構(gòu)造函數(shù);第二種情況是定義內(nèi)置函數(shù)時(shí),將它放在類定義體外,但在該成員函數(shù)定義前插入inline關(guān)鍵字,使它仍然起內(nèi)置函數(shù)的作用。如案例一中的inlinestu::~stu()的析構(gòu)函數(shù)。12/23/2024549.3.3對(duì)象

1.對(duì)象的定義對(duì)象的定義可以采用以下的兩種方式:(1)在聲明類的同時(shí),直接定義對(duì)象,就是在聲明類的右花括號(hào)“}”后,直接寫出屬于該類的對(duì)象名表。如案例一中的stuA("張三",18,0)。stuA是使用全局類定義的全局對(duì)象。(2)先聲明類,在使用時(shí)再定義對(duì)象。如案例一中stustuB("李四",19,0);stuB是使用全局類定義的局部對(duì)象。對(duì)象是類的實(shí)例,是類型為類的變量,也有對(duì)象數(shù)組、對(duì)象指針、對(duì)象形參、返回對(duì)象數(shù)據(jù)的函數(shù)等情況,這里不再一一敘述。2.對(duì)象的引用對(duì)象的引用是指對(duì)對(duì)象成員的引用。不論是數(shù)據(jù)成員還是成員函數(shù),只要是公有的,就可以被外部函數(shù)直接引用。引用的格式是:對(duì)象名.數(shù)據(jù)成員名或?qū)ο竺?成員函數(shù)名(實(shí)參表)由于成員函數(shù)中隱含了指向當(dāng)前對(duì)象(是指調(diào)用成員函數(shù)的對(duì)象)的指針,成員函數(shù)可以直接引用對(duì)象的數(shù)據(jù)成員名。類在函數(shù)外定義的稱為全局類,在函數(shù)內(nèi)部定義的稱為局部類。同樣,對(duì)象也有全局對(duì)象和局部對(duì)象的分類。全局對(duì)象只能由全局類來定義。12/23/2024553.關(guān)于this指針在C++?中,定義了一個(gè)this指針,它是成員函數(shù)所屬對(duì)象的指針,它指向類對(duì)象的地址,成員函數(shù)通過這個(gè)指針可以知道自己屬于哪一個(gè)對(duì)象,也就是由哪一個(gè)對(duì)象來調(diào)用的成員函數(shù)。this指針是一種隱含指針,它隱含于每個(gè)類的成員函數(shù)中,僅能在類的成員函數(shù)中訪問,不需要定義就可以使用。因此,成員函數(shù)訪問類中數(shù)據(jù)成員的格式也可以寫成:this->成員變量下面定義一個(gè)類Date。classDate{private:intyear,month,day;public:voidsetYear(int);voidsetMonth(int);voidsetDay(int);};該類的成員函數(shù)setMonth可用以下兩種方法實(shí)現(xiàn):方法1:voidDate::setMonth(intmn) //使用隱含的this指針{

month=mn;}方法2:voidDate::setMonth(intmn) //顯式使用this指針{this->month=mn;}12/23/202456雖然顯式使用this指針的情況并不是很多,但是this指針有時(shí)必須顯式使用。例如,下面的賦值語句是不允許的:voidDate::setMonth(intmonth){month=month;}//形參month和成員month同名時(shí),默認(rèn)指的是形參,相當(dāng)于形參自己給自己賦值為了給同名的數(shù)據(jù)成員賦值,可以用this指針來解決:voidDate::setMonth(intmonth){this->month=month;//this->month是類Date的數(shù)據(jù)成員,month是函數(shù)setMonth()的形參}12/23/202457例9.15this指針示例。#include<iostream.h>classPoint{intx,y;public:Point(inta,intb){x=a;y=b;}voidMovePoint(inta,intb){this->x+=a;this->y+=b;}voidprint(){cout<<"x="<<x<<"y="<<y<<endl;}};voidmain(){Pointpoint1(10,10);point1.MovePoint(2,2);point1.print();}12/23/202458當(dāng)一個(gè)對(duì)象調(diào)用成員函數(shù)時(shí),該成員函數(shù)的this指針便指向這個(gè)對(duì)象。如果不同的對(duì)象調(diào)用同一個(gè)成員函數(shù),則C++?編譯器將根據(jù)該成員函數(shù)的this指針指向的對(duì)象來確定應(yīng)該引用哪一個(gè)對(duì)象的數(shù)據(jù)成員。當(dāng)在類的非靜態(tài)成員函數(shù)中訪問類的非靜態(tài)成員的時(shí)候,編譯器會(huì)自動(dòng)將對(duì)象本身的地址作為一個(gè)隱含參數(shù)傳遞給函數(shù)。也就是說,即使你沒有寫上this指針,編譯器在編譯的時(shí)候也是加上this的,它作為非靜態(tài)成員函數(shù)的隱含形參,對(duì)各成員的訪問均通過this進(jìn)行。當(dāng)對(duì)象point1調(diào)用MovePoint(2,2)函數(shù)時(shí),即將point1對(duì)象的地址傳遞給了this指針。MovePoint函數(shù)的原型應(yīng)該是voidMovePoint(Point*this,inta,intb);第一個(gè)參數(shù)是指向該類對(duì)象的一個(gè)指針,我們?cè)诙x成員函數(shù)時(shí)沒看見是因?yàn)檫@個(gè)參數(shù)在類中是隱含的。這樣point1的地址傳遞給了this,所以在MovePoint函數(shù)中便顯式的寫成:voidMovePoint(inta,intb){this->x+=a;this->y+=b;}。在實(shí)際編程中,由于不標(biāo)明this指針的形式使用起來更加方便,因此大部分程序員都使用簡(jiǎn)寫形式。12/23/2024599.4構(gòu)造函數(shù)和析構(gòu)函數(shù)

在C++?中,有兩種特殊的成員函數(shù),即構(gòu)造函數(shù)和析構(gòu)函數(shù)。12/23/2024609.4.1構(gòu)造函數(shù)

C++?中定義了一種特殊的初始化函數(shù),稱之為構(gòu)造函數(shù)。創(chuàng)建對(duì)象時(shí),自動(dòng)調(diào)用構(gòu)造函數(shù)。構(gòu)造函數(shù)具有一些特殊的性質(zhì):構(gòu)造函數(shù)的名字必須與類名相同;構(gòu)造函數(shù)可以有任意類型的參數(shù),但不能具有返回類型;定義對(duì)象時(shí),編譯系統(tǒng)會(huì)自動(dòng)地調(diào)用構(gòu)造函數(shù)。(1)構(gòu)造函數(shù)不能像其他成員函數(shù)那樣被顯式地調(diào)用,它是在定義對(duì)象的同時(shí)調(diào)用的,其一般格式為類名對(duì)象名(實(shí)參表);如案例一中:stustuB("李四",19,0);(2)在實(shí)際應(yīng)用中,通常需要給每個(gè)類定義構(gòu)造函數(shù)。如果沒有給類定義構(gòu)造函數(shù),則編譯系統(tǒng)自動(dòng)地生成一個(gè)缺省的構(gòu)造函數(shù)。例如,如果沒有給stu類定義構(gòu)造函數(shù),編譯系統(tǒng)則為stu生成下述形式的構(gòu)造函數(shù):stu::stu(){}這個(gè)缺省的構(gòu)造函數(shù)不帶任何參數(shù),它只為對(duì)象開辟一個(gè)存儲(chǔ)空間,而不能給對(duì)象中的數(shù)據(jù)成員賦初值,這時(shí)的初始值是隨機(jī)數(shù),程序運(yùn)行時(shí)可能會(huì)造成錯(cuò)誤。因此給對(duì)象賦初值是非常重要的。給對(duì)象賦初值并不是只能采用構(gòu)造函數(shù)這一途徑,如案例一中stuC.set("王五",20,0);就是給對(duì)象stuC賦值的;這種通過顯式調(diào)用成員函數(shù)來進(jìn)行對(duì)象賦初值是完全允許的。但是這種方法存在一些缺陷,比如,對(duì)每一個(gè)對(duì)象賦初值都需要一一給出相應(yīng)的語句,因此容易遺漏而產(chǎn)生錯(cuò)誤。而構(gòu)造函數(shù)的調(diào)用不需要寫到程序中,是系統(tǒng)自動(dòng)調(diào)用的,所以不存在遺忘的問題。兩者相比,選擇構(gòu)造函數(shù)的方法為對(duì)象進(jìn)行初始化比較合適。12/23/202461(3)構(gòu)造函數(shù)可以是不帶參數(shù)的。例如:classabc{private:inta;public:abc(){cout<<"initialized"<<endl;a=5;}};

此時(shí),類abc的構(gòu)造函數(shù)就沒有帶參數(shù)。在main()函數(shù)中可以采用如下方法定義對(duì)象:abcs;在定義對(duì)象s的同時(shí),構(gòu)造函數(shù)s.abc::abc()被系統(tǒng)自動(dòng)調(diào)用執(zhí)行,執(zhí)行結(jié)果是:在屏幕上顯示字符串“initialized”,并給私有數(shù)據(jù)成員a賦值5。12/23/202462(4)構(gòu)造函數(shù)也可以采用構(gòu)造初始化表對(duì)數(shù)據(jù)成員進(jìn)行初始化,例如:classA{inti;charj;floatf;public:A(intx,chary,floatz){i=x;j=y;f=z;}};這個(gè)含有三個(gè)數(shù)據(jù)成員的類,利用構(gòu)造初始化表的方式可以寫成:classA{inti;charj;floatf;public:A(intx,chary,floatz):i(x),j(y),f(z){}};(5)缺省參數(shù)的構(gòu)造函數(shù)。在實(shí)際使用中,有些構(gòu)造函數(shù)的參數(shù)值通常是不變的,只有在特殊情況下才需要改變它的參數(shù)值。這時(shí)可以將其定義成帶缺省參數(shù)的構(gòu)造函數(shù),例如:#include<iostream.h>classPoint{

intxVal,yVal;public:

Point(intx=0,inty=0)

{xVal=x;yVal=y;}

voiddisplay()

{cout<<xVal<<""<<yVal<<endl;}};在類Point中,構(gòu)造函數(shù)的兩個(gè)參數(shù)均含有缺省參數(shù)值,因此,在定義對(duì)象時(shí)可根據(jù)需要使用其缺省值。下面我們用main()函數(shù)來使用它。voidmain(){Pointp1; //不傳遞參數(shù),全部使用缺省值

Pointp2(2); //只傳遞一個(gè)參數(shù)

Pointp3(2,3); //傳遞兩個(gè)參數(shù)}12/23/202463在上面定義了三個(gè)對(duì)象p1、p2、p3,它們都是合法的對(duì)象。由于傳遞參數(shù)的個(gè)數(shù)不同,使它們的私有數(shù)據(jù)成員取得不同的值。由于定義對(duì)象p1時(shí),沒有傳遞參數(shù),所以xVal和yVal全取構(gòu)造函數(shù)的缺省值為其賦值,因此均為0。在定義對(duì)象p2時(shí),只傳遞了一個(gè)參數(shù),這個(gè)參數(shù)傳遞給構(gòu)造函數(shù)的第一個(gè)參量,而第二個(gè)參量取缺省值,所以對(duì)象p2的xVal取值2,yVal取值0。在定義對(duì)象p3時(shí),傳遞了兩個(gè)參數(shù),這兩個(gè)參數(shù)分別傳給了xVal和yVal,因此xVal取值2,yVal取值3。同一個(gè)函數(shù)名,由于使用的參數(shù)類型和個(gè)數(shù)不同,從而執(zhí)行不同的函數(shù)體的,這種行為稱之為函數(shù)的重載。12/23/2024649.4.2復(fù)制構(gòu)造函數(shù)

復(fù)制構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù)。它用于依據(jù)已存在的對(duì)象建立一個(gè)新對(duì)象。典型的情況是,將參數(shù)代表的對(duì)象逐域復(fù)制到新創(chuàng)建的對(duì)象中。用戶可以根據(jù)自己的需要定義復(fù)制構(gòu)造函數(shù),系統(tǒng)也可以為類產(chǎn)生一個(gè)缺省的復(fù)制構(gòu)造函數(shù)。1.自定義復(fù)制構(gòu)造函數(shù)自定義復(fù)制構(gòu)造函數(shù)的一般形式如下:classname(constclassname&ob){//復(fù)制構(gòu)造函數(shù)的函數(shù)體}其中,ob是用來初始化的另一個(gè)對(duì)象的對(duì)象的引用。12/23/202465下面是一個(gè)用戶自定義的復(fù)制構(gòu)造函數(shù):classPoint{intxVal,yVal;public:Point(intx,inty) //構(gòu)造函數(shù)

{xVal=x;yVal=y;}Point(constPoint&p) //復(fù)制構(gòu)造函數(shù)

{xVal=2*p.xVal;yVal=2*p.yVal;}//…};例如p1、p2為類Point的兩個(gè)對(duì)象,且p1已經(jīng)存在,則下述語句可以調(diào)用復(fù)制構(gòu)造函數(shù)初始化p2:Pointp2(p1);12/23/202466下面給出使用自定義復(fù)制構(gòu)造函數(shù)的完整程序。例9.16自定義Point類復(fù)制構(gòu)造函數(shù)。#include<iostream.h>classPoint{intxVal,yVal;public:Point(intx,inty) //構(gòu)造函數(shù)

{xVal=x;yVal=y;}Point(constPoint&p) //復(fù)制構(gòu)造函數(shù)

{xVal=2*p.xVal;yVal=2*p.yVal;}

voidprint(){cout<<xVal<<""<<yVal<<endl;}};12/23/202467voidmain(){Pointp1(30,40); //定義類Point的對(duì)象p1Pointp2(p1); //顯示調(diào)用復(fù)制構(gòu)造函數(shù),創(chuàng)建對(duì)象p2p1.print();p2.print();}本例在定義對(duì)象p2時(shí),調(diào)用了自定義復(fù)制構(gòu)造函數(shù)。程序運(yùn)行結(jié)果如下:30406080本例除了顯式調(diào)用復(fù)制構(gòu)造函數(shù)外,還可以采用賦值形式調(diào)用復(fù)制構(gòu)造函數(shù)。例如將主函數(shù)main()改寫成如下形式:voidmain(){Pointp1(30,40);Pointp2=p1; //使用賦值形式調(diào)用復(fù)制構(gòu)造函數(shù),創(chuàng)建對(duì)象p2p1.print();p2.print();}在定義對(duì)象p2時(shí),雖然從形式上看是將對(duì)象p1賦值給了對(duì)象p2,但實(shí)際上調(diào)用的是復(fù)制構(gòu)造函數(shù),在對(duì)象p2被創(chuàng)建時(shí),將對(duì)象p1的值逐域復(fù)制給對(duì)象p2,運(yùn)行結(jié)果同上。12/23/2024682.缺省的復(fù)制構(gòu)造函數(shù)如果沒有編寫自定義的復(fù)制構(gòu)造函數(shù),C++?會(huì)自動(dòng)地將一個(gè)已存在的對(duì)象賦值給新對(duì)象,這種按成員逐一復(fù)制的過程是由缺省復(fù)制構(gòu)造函數(shù)自動(dòng)完成的。例9.17將例9.16中的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論