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

下載本文檔

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

文檔簡介

1第九章類與對象

C

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

{intX=25;//語句塊內的局部變量

::X=30;//編譯報錯:X不是全局變量

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

if(!p){cout<<"分配失敗"<<endl;return1;}*p=10;cout<<*p;deletep; //釋放p指向的存儲空間}若動態(tài)分配失敗,則程序將顯示“分配失敗”。為了避免程序出錯,建議在動態(tài)分配內存時對是否分配成功進行檢查。12/23/2024189.1.3引用前面學習了指針的概念,指針就是內存單元的地址,它可能是變量的地址,也可能是函數(shù)的入口地址。C++?引入了另外一個同指針相關的概念:引用。先看一個例子。例9.7值傳遞應用。#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讓我們來分析一下這個例子。首先在內存空間為a、b開辟兩個存儲單元并賦初值,然后調用swap函數(shù),swap函數(shù)為x、y開辟了存儲空間,并將a、b的值傳遞給x、y。x、y的值互換了,在swap結束時,x、y的生存周期結束,存儲空間被收回。所以a、b的值并沒有互換。此時輸出:a=2,b=1a=2,b=1可以使用指針傳遞的方式解決這個問題,我們改寫上面的程序。例9.8使用指針(地址)進行值傳遞。#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程序首先在內存空間為a、b開辟兩個存儲單元并賦初值,然后調用swap函數(shù),swap函數(shù)為指針x、y開辟了存儲空間,并將a、b的地址傳遞給x、y。在swap函數(shù)中,對x、y的間接引用的訪問就是對a、b的訪問,從而交換了a、b的值。那么C++?中還有沒有更簡單的方式呢?有,那就是引用。引用是能自動進行間接引用的一種指針。自動間接引用就是不必使用間接引用運算符*,就可以得到一個引用值。我們可以這樣理解,引用就是某一變量(目標)的一個別名,兩者占據(jù)同樣的內存單元,對引用的操作與對變量直接操作完全一樣。12/23/2024211.引用的定義定義引用的關鍵字是“type&”,它的含義是“type類型的引用”。例如:inta=5;int&b=a;它創(chuàng)建了一個整型引用,b是a的別名,a和b占用內存同一位置。當a變化時,b也隨之變化,反之亦然。引用的初始值可以是一個變量或另一個引用,以下的定義也正確。inta=5;int&b=a;int&b1=b;12/23/2024222.使用規(guī)則(1)定義引用時,必須立即初始化。inta;int&b; //錯誤,沒有初始化b=a;(2)引用不可重新賦值。inta,k;int&b=a;b=&k; //錯誤,重新賦值(3)引用不同于普通變量,下面的聲明是非法的:int&b[3]; //不能建立引用數(shù)組int&*P; //不能建立指向引用的指針int&&r; //不能建立指向引用的引用12/23/202423(4)當使用&運算符取一個引用的地址時,其值為所引用的變量的地址。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;}當程序中調用函數(shù)swap()時,實參a、b分別初始化引用x和y,所在函數(shù)swap()中,x和y分別引用a和b,對x和y的訪問就是對a和b的訪問,所以函數(shù)swap()改變了main()函數(shù)中變量a和b的值。盡管通過引用參數(shù)產生的效果同按地址傳遞是一樣的,但其語法更清楚簡單。C++?主張用引用傳遞取代地址傳遞的方式,因為前者語法容易且不易出錯。12/23/2024259.1.4C++?中的函數(shù)C++?對傳統(tǒng)的C函數(shù)說明作了一些改進。這些改進主要是為了滿足面向對象機制的要求,以及可靠性、易讀性的要求。1.主函數(shù)mainC并無特殊規(guī)定main()函數(shù)的格式,因為通常不關心返回何種狀態(tài)給操作系統(tǒng)。然而,C++?卻要求main()函數(shù)匹配下面兩種原型之一:voidmain() //無參數(shù),無返回類型intmain(intargc,char*argv[]) //帶參數(shù),有返回類型,參數(shù)也可以省略如果前面不寫返回類型,那么main()等價于intmain()。函數(shù)要求具有int返回類型,如例9.9。12/23/2024262.函數(shù)原型函數(shù)原型的概念在前面的章節(jié)已提及,函數(shù)原型實際上就是對函數(shù)的頭格式進行說明,包含函數(shù)名、參數(shù)及返回值類型。C語言建議編程者為程序中的每一個函數(shù)建立原型,而C++?要求必須為每一個函數(shù)建立原型。有了函數(shù)原型編譯程序方能進行強類型檢查,從而確保函數(shù)調用的實參類型與要求的類型相符。早期的C正是缺乏這種強類型檢查,很容易造成非法參數(shù)值傳遞給函數(shù),因此造成程序運行時不可預料的錯誤。函數(shù)原型的語法形式一般為返回類型函數(shù)名(參數(shù)表);函數(shù)原型是一條語句,它必須以分號結束。它由函數(shù)的返回類型、函數(shù)名和參數(shù)表構成。參數(shù)表包含所有參數(shù)及它們的類型,參數(shù)之間用逗號分開。請看下面的例子。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在程序中,要求一個函數(shù)的原型出現(xiàn)在該函數(shù)的調用語句之前。這樣,當一個函數(shù)的定義在后,而對它的調用在前時,必須將該函數(shù)的原型放在調用語句之前;但當一個函數(shù)的定義在前,對它的調用在后,一般就不必再單獨給出它的原型了,如例9.9所示。說明:(1)函數(shù)原型的參數(shù)表中可以不包含參數(shù)的名字,而是包含它們的類型,但函數(shù)定義的函數(shù)說明部分中的參數(shù)必須給出名字,而且不包含結尾的分號。例如:voidmax(int,int); //函數(shù)原型的聲明voidmax(intm,intn) //函數(shù)定義的函數(shù)說明部分{

//…}(2)原型說明中沒有指出返回類型的函數(shù)(包括主函數(shù)main),C++?默認該函數(shù)的返回類型是int,因此以下的原型說明在C++?中是等價的:fun(inta);intfun(inta);12/23/2024293.內置函數(shù)函數(shù)調用導致了一定數(shù)量的額外開銷,如參數(shù)壓棧、出棧等。有時正是這種額外開銷迫使C程序員放棄使用函數(shù)調用,進行代碼復制以提高效率。C++?的內置函數(shù)正好解決這一問題。當函數(shù)定義是由inline開頭時,表明此函數(shù)為內置函數(shù)。編譯時,使用函數(shù)體中的代碼替代函數(shù)調用表達式,從而完成與函數(shù)調用相同的功能,這樣能加快代碼的執(zhí)行,減少調用開銷。例如:inlineintsum(inta,intb) //內置函數(shù){returna+b;}值得注意的是:內置函數(shù)必須在它被調用之前定義,否則編譯不會得到預想的結果。若內置函數(shù)較長,且調用太頻繁時,程序將加長很多。因此,通常只有較短的函數(shù)才定義為內置函數(shù),對于較長的函數(shù),最好作為一般函數(shù)處理。12/23/2024304.缺省參數(shù)值C++?對C函數(shù)的重要的改進之一就是可以為函數(shù)定義缺省的參數(shù)值。例如:intfunction(intx=2,inty=6);//函數(shù)給出缺省的參數(shù)值x與y的值分別是2和6。當進行函數(shù)調用時,編譯器按從左向右順序將實參與形參結合,若未指定足夠的實參,則編譯器按順序用函數(shù)原型中的缺省值來補足所缺少的實參。例如:function(1,2); //x=1,y=2function(1); //x=1,y=6function(); //x=2,y=6一個C++?函數(shù)可以有多個缺省參數(shù),并且C++?要求缺省參數(shù)必須連續(xù)的放在函數(shù)參數(shù)表的尾部,也就是說,所有取缺省值的參數(shù)都必須出現(xiàn)在不取缺省值的參數(shù)的右邊。當調用具有多個缺省參數(shù)時,若某個參數(shù)省略,則其后的參數(shù)皆應省略而采用缺省值。當不允許出現(xiàn)某個參數(shù)省略時,再對其后的參數(shù)指定參數(shù)值。例如:function(,3) //這種調用方式是錯誤的12/23/2024315.函數(shù)重載在C語言中,函數(shù)名必須是唯一的,也就是說不允許出現(xiàn)同名的函數(shù)。當要求編寫求整數(shù)、浮點數(shù)和雙精度浮點數(shù)的立方數(shù)的函數(shù)時,若用C語言來處理,必須編寫三個函數(shù),這三個函數(shù)的函數(shù)名不允許同名。例如:Icube(inti); //求整數(shù)的三次方Fcube(floatf); //求浮點數(shù)的三次方Dcube(doublei); //求雙精度浮點數(shù)的三次方當使用這些函數(shù)求某個數(shù)的立方數(shù)時,必須調用合適的函數(shù),也就是說,用戶必須記住這三個函數(shù),雖然這三個函數(shù)的功能是相同的。在C++?中,用戶可以重載函數(shù),只要函數(shù)參數(shù)的類型不同,或者參數(shù)的個數(shù)不同,兩個或兩個以上的函數(shù)可以使用相同的函數(shù)名。一般而言,重載函數(shù)應執(zhí)行相同的功能。我們可用函數(shù)重載來重寫上面的三個函數(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()中三次調用了cube()函數(shù),實際上調用了三個不同的版本。由系統(tǒng)根據(jù)傳送的參數(shù)類型的不同來決定調用哪個重載版本。值得注意的是重載函數(shù)應在參數(shù)個數(shù)或參數(shù)類型上有所不同,否則編譯程序將無法確定調用哪一個重載版本,即使返回類型不同,也不能區(qū)分。例如:intfun(intx,inty);floatfun(intx,inty);上面的重載就是錯誤的。12/23/2024349.2C++?的輸入與輸出C語言提供了強有力的I/O函數(shù),其功能強,靈活性好,是很多語言無法比擬的。但C++?為何還要定義自己的I/O系統(tǒng),而不建議使用C語言原有的函數(shù)呢?在C語言中進行I/O操作時,常會出現(xiàn)以下錯誤:inti;floatf;scanf("%f",i);printf("%d",f);這些錯誤C語言編譯器是不能檢查出來的,而在C++?中,可以將上面的操作寫成:inti;floatf;cin>>i;cout<<f;12/23/202435cin是標準的輸入流,在程序中用于代表標準輸入設備,即鍵盤。運算符“>>”是輸入運算符,表示從標準輸入流(即鍵盤)讀取的數(shù)值傳送給右方指定的變量。運算符“>>”允許用戶連續(xù)讀入一連串數(shù)據(jù),兩個數(shù)據(jù)間用空格、回車或Tab鍵進行分割。例如:cin>>x>>y;cout是標準的輸出流,在程序中用于代表標準輸出設備,通常指屏幕。運算符“<<”是輸出運算符,表示將右方變量的值顯示到屏幕上。運算符“<<”允許用戶連續(xù)輸出數(shù)據(jù)。例如:cout<<x<<y;這里的變量應該是基本數(shù)據(jù)類型,不能是void型。其實,可以在同一程序中混用C語言和C++?語言的I/O操作,繼續(xù)保持C語言的靈活性。因而,在把C語言程序改為C++?語言程序時,并不一定要修改每一個I/O操作。12/23/2024369.2.1C++?的流類結構C++?語言和C語言的I/O系統(tǒng)都是對流(tream)進行操作。流實際上就是一個字節(jié)序列。輸入操作中,字節(jié)從輸入設備(如鍵盤、磁盤、網(wǎng)絡連接等)流向內存;輸出操作中,字節(jié)從內存流向輸出設備。使用C++?式的I/O的程序必須包含頭文件iostream.h,對某些流函數(shù)可能還需要其他頭文件,例如進行文件I/O時需要頭文件fstream.h。1.?iostream庫iostream庫中具有streambuf和ios兩個平行的類,這都是基本的類,分別完成不同的工作。streambuf類提供基本流操作,但不提供格式支持。類ios為格式化I/O提供基本操作。2.標準流iostream.h說明了標準流對象cin、cout、cerr與clog。cin是標準輸入流,對應于C語言的stdin;cout是標準輸出流,對應于C語言的stdout;cerr是標準出錯信息輸出,clog是帶緩沖的標準出錯信息輸出。cerr和clog流被連到標準輸出上對應于C語言的stderr。cerr和clog之間的區(qū)別是cerr沒有緩沖,發(fā)送給它的任何輸出立即被執(zhí)行,而clog只有當緩沖區(qū)滿時才有輸出。缺省時,C++?語言標準流被連到控制臺上。12/23/2024379.2.2格式化I/O

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

private: //訪問權限設置,后面的成員為私有,直到下一個權限設置進行更改

charname[20]; //學生姓名

intage; //學生年齡

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

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

public: //訪問權限設置,后面的成員為公有訪問屬性

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

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

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

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

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

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

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

{age++;}}stuA("張三",18,0); //類stu的封裝,定義stuA是全局對象inlinestu::~stu() //析構函數(shù)在類外定義{stunumber--;cout<<this->name<<"經(jīng)過"<<studyyear<<"年學習已經(jīng)畢業(yè)!"<<endl;//cout是輸入流對象,使用需要頭文件iostream.h,this是函數(shù)隱含的對象指針參數(shù),指向調用該函數(shù)的對象}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)<<"學生總數(shù)"<<setw(10)<<"姓名"\<<setw(10)<<"年齡"<<setw(10)<<"學習年數(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ù)成員的初始化必須放在類外進行intstu::stunumber=0;12/23/202449voidmain(){intx; //動態(tài)變量x表示畢業(yè)需要的學制

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

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

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

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

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

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

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

{stuA.addage();stuB.addage();stuC.addage();stu::addstudyyear(); //增加學習時間

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

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

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

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

month=mn;}方法2:voidDate::setMonth(intmn) //顯式使用this指針{this->month=mn;}12/23/202456雖然顯式使用this指針的情況并不是很多,但是this指針有時必須顯式使用。例如,下面的賦值語句是不允許的:voidDate::setMonth(intmonth){month=month;}//形參month和成員month同名時,默認指的是形參,相當于形參自己給自己賦值為了給同名的數(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當一個對象調用成員函數(shù)時,該成員函數(shù)的this指針便指向這個對象。如果不同的對象調用同一個成員函數(shù),則C++?編譯器將根據(jù)該成員函數(shù)的this指針指向的對象來確定應該引用哪一個對象的數(shù)據(jù)成員。當在類的非靜態(tài)成員函數(shù)中訪問類的非靜態(tài)成員的時候,編譯器會自動將對象本身的地址作為一個隱含參數(shù)傳遞給函數(shù)。也就是說,即使你沒有寫上this指針,編譯器在編譯的時候也是加上this的,它作為非靜態(tài)成員函數(shù)的隱含形參,對各成員的訪問均通過this進行。當對象point1調用MovePoint(2,2)函數(shù)時,即將point1對象的地址傳遞給了this指針。MovePoint函數(shù)的原型應該是voidMovePoint(Point*this,inta,intb);第一個參數(shù)是指向該類對象的一個指針,我們在定義成員函數(shù)時沒看見是因為這個參數(shù)在類中是隱含的。這樣point1的地址傳遞給了this,所以在MovePoint函數(shù)中便顯式的寫成:voidMovePoint(inta,intb){this->x+=a;this->y+=b;}。在實際編程中,由于不標明this指針的形式使用起來更加方便,因此大部分程序員都使用簡寫形式。12/23/2024599.4構造函數(shù)和析構函數(shù)

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

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

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

intxVal,yVal;public:

Point(intx=0,inty=0)

{xVal=x;yVal=y;}

voiddisplay()

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

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

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

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

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

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

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

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

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

溫馨提示

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

評論

0/150

提交評論