



版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
C++面向?qū)ο缶幊藽hapter!C++基礎知識3.1Questionl:函數(shù)模板:如果兩個函數(shù)的參數(shù)個數(shù)相同,函數(shù)的行為相同(做同樣的事),只是函數(shù)類型和參數(shù)的數(shù)據(jù)類型不同,如果用函數(shù)重載的話,編寫的函數(shù)代碼是相同的,為了節(jié)省時間,C++提供了函數(shù)模板功能。格式:templatetypename標識符しtypename標識符, ]函數(shù)定義(函數(shù)的類型和參數(shù)的類型用聲明的標識符表示)template是關(guān)鍵字,含義是模板typename是關(guān)鍵字,表示其后的標識符代表類型參數(shù),調(diào)用時根據(jù)實參的類型確定形參的類型。所謂函數(shù)模板,是建立一個通用函數(shù),不指定函數(shù)類型和參數(shù)類型,而用ー個虛擬的類型表示。在調(diào)用函數(shù)時,用實參的類型取代模板中的虛擬類型。Example:為計算兩個數(shù)中的大數(shù)定義函數(shù)模板:#include<iostream>usingnamespacestd;template<typenameT>Tmax(Ta,Tb,Tc)〃用虛擬類型T表示類型{if(b>a)a=b;if(c>a)a=c;returna;C++提供了為變量取別名的功能,這就是變量的引用。格式:類型&變量1=變量2變量2是在此之前已經(jīng)定義過的變量,且與變量1的類型相同。這里為變量2定義ー個別名變量丨,在程序里變量丨和變量2就是同一個變量。注意:兩個變量不能用同一個別名例:int。=3,b=4;int&c=a;//c是c!的別名int&c=b;/Z錯誤的用法ー個變量可以有多個別名例:inta=3;int&b=a;int&c=b;變量Q有兩個別名b和Co#include<iostream>usingnamespacestd;intmain()(inta=10;int&b=a;〃聲明b是a的引用a=a*a;〃。的值變化了,b的值也應ー起變化cout?a?""?b?endl;b=b/5; 〃b的值變化了,。的值也應ー起變化cout?b?""?a?endl;return0;)3.3Questions:對引用的進ー步說明:(1)引用變量都具有非void類型(2)不能建立引用的數(shù)組(3)可以建立常引用變量,不允許修改常引用變量的值例:inti;constint&a=i;a=3;/Z錯誤的用法i=8; //i不是常變?,可以修改inti;ini*p=&i;int*&pt=p;〃pt是p的別名變量,同時/Z也是指針變量C++提供了一種機制,在編譯時,將所調(diào)用的函數(shù)的代碼嵌入到調(diào)用函數(shù)代碼中,在執(zhí)行函數(shù)時省去了調(diào)用環(huán)節(jié),提高了函數(shù)的執(zhí)行速度。這種機制稱為內(nèi)置函數(shù),有的書稱內(nèi)聯(lián)函數(shù).格式:inline函數(shù)類型函數(shù)名(形參表)(函數(shù)體}inline是C++的關(guān)鍵字,在編譯時,編譯程序會把這個函數(shù)嵌入到調(diào)用函數(shù)的函數(shù)體中調(diào)用格式:函數(shù)名(實參表)Example#include<iostream>usingnamespacestd;inlineintmaxfintajntbjntc)/Z這是一個內(nèi)置函數(shù),/Z求3個整數(shù)中的最大者{if(b>a)a=b;if(c>a)a=c;returna;)intmain(){inti=7,j=10,k=25,m;m=max(ij,k);cout?"max="?m?endl;return0;)由于在定義函數(shù)時指定它是內(nèi)置函數(shù),因此編譯系統(tǒng)在遇到函數(shù)調(diào)用max(i.j,k)時就用max函數(shù)體的代碼代替max(i,j,k),同時用實參代替形參。調(diào)用語句m=max(i,j,k)就被置換成:{a=i;b=j;c=k;if(b>a)a=b;if(c>a)a=c;m=a;)使用內(nèi)置函數(shù)可以節(jié)省程序的運行時間,但增加了目標程序的長度。所以在使用時要衡量時間和空間的得失。并不是所有的變量在程序運行的時時刻刻都是可見的。有的變量在整個程序運行期間都是可見的,稱它們?yōu)槿肿兞?有的變量只能在一個函數(shù)中可知,被稱為局部變量.每個變量都有其有效的作用域.程序只能在變量的有效的作用域內(nèi)使用變量,不能直接使用其他域中的變量木呈「ア白勺iAj彳字iXよ或程中的內(nèi)存?仝間代碼區(qū)程序中名?個函數(shù)的代碼全局數(shù)據(jù)區(qū)程序中全局數(shù)據(jù)和靜態(tài)數(shù)據(jù)堆區(qū)程序中的動態(tài)數(shù)據(jù)校區(qū)程FF中各函數(shù)內(nèi)的數(shù)據(jù)例1.16局部變量和全局變量同名#include<iostream>usingnamespacestd;floata=13.5;intmain(){inta=5;cout?a?endl;return0; }程序中有兩個變量a,ー個是全局變量,另ー個是main函數(shù)的局部變量,根據(jù)局部變量會屏蔽同名的全局變量規(guī)則,在函數(shù)中出現(xiàn)的變量a是局部變量,因此輸出的值是5,而不是13.5,為了在函數(shù)中訪問全局變量C++提供了作用域運算符::,可以用來指定要訪問的作用域,可以把main函數(shù)改寫成#include<iostream>usingnamespacestd;floata=13.5;intmain(){inta=5;cout?a?endl;cout?::a?endl;return0;}::a表示全局變量a。注意不能用::訪問局部變量。C++提供了字符串類類型string,實際上它不是C++的基本類型,它是在C++標準庫中聲明的ー個字符串類,程序可以用它定義對象。.定義字符串變量格式:string變量名表;可以在定義變量時用字符串常量為變量賦初值:string變量名=字符串常量注意:如用字符串變量,在程序開始要用包含語句把C++標準庫的string頭文件包含進來。字符串操作對字符串變量賦值字符串變量=字符串表達式例:stringstl,st2;cfl="王占占"?t2=stl;訪問字符串中的字符C++允許把字符串作為字符數(shù)組,第一個字符的下標是0.第二個字符的下標是1,以此類推。例:stringw=**then";w⑵=七’;結(jié)果字符串W變成than③輸入輸出字符串格式:cin?字符串變量cout<〈字符串變量④字符串連接運算格式:字符串1+字符串2功能:把連接運算符兩端的字符連接成一個字符串。表達式中可以用字符串常量也可以用字符串變量。例:stringstl="C++";,stringst2="Language";stl=stl+st2;,結(jié)果是C++Language⑤字符串的比較運算可以用關(guān)系運算符>、>=、==、!=、<、<=對兩個字符串同一位置的字符進行比較,根據(jù)ASCII碼值判定字符的大小。"例:"china">"Chinese"運算結(jié)果是假。動態(tài)分配ノ撤銷內(nèi)存的運算符new和delete分配內(nèi)存運算new類型[(初值)]類型是決定分配空間尺寸的關(guān)鍵元素,如果運算結(jié)果正確,它的值是分配內(nèi)存空間的起始地址,否則返回NULL。,例:int*a=newint;int*b=newint(100);char*ch=newchar[10];int*q=newint[5][4];float*p=newfloat(3.14159);歸還動態(tài)內(nèi)存運算,delete[]指針變量[]代表數(shù)組,如果不是數(shù)組可以省略口。運算功能:撤銷指針變量所指的動態(tài)內(nèi)存空間,指針變量的數(shù)據(jù)類型決定了空間尺寸的大小。例:char*p=newchar[10];delete[]p;例1?18用動態(tài)內(nèi)存存放結(jié)構(gòu)體變量#include<iostream>#include<string.h>usingnamespacestd;structstudent{charname[10];intnum;charsex;);{student*p;p=newstudent;strcpy(p->name,"WangFun");p->num=10123;p->sex='M';cout?p->name?""?p->num?""?p->sex?endl;deletep;return0;)先聲明了一個結(jié)構(gòu)體類型student,定義ー個指向它的指針變量p,用new開辟ー個空間存放ー個student類型變量。如果無法正常分配內(nèi)存,運算會返回一個空指針NULL,程序可以設計判斷結(jié)構(gòu),根據(jù)判斷結(jié)果決定怎樣操作。注意不要混合使用{new、delete};{mctlloc、free}。要正確搭配,不要用new分配內(nèi)存后,又用free釋放內(nèi)存。Chapter2類和對象面向?qū)ο蟪绦蛟O計方法概述對于規(guī)模比較小的程序,程序員可以直接編寫出ー個面向過程的程序,能詳細地描述每一瞬間的數(shù)據(jù)結(jié)構(gòu)和對其操作的過程。但是當程序規(guī)模越來越大,面向過程的程序語言就顯得力不從心,面向?qū)ο蟪绦蛟O計語言就應運而生,C++就是其中的一個成員。什么是面向?qū)ο蟮某绦蛟O計面向?qū)ο蟮某绦蛟O計的思路與人們?nèi)粘I钪刑幚韱栴}的思路是相似的。ー個復雜的事物總是由許多部分組成的。例如,一輛汽車是由發(fā)動機、底盤、車身和車輪等部件組成。當人們生產(chǎn)汽車時,不是先設計和制造發(fā)動機,再設計和制造底盤,然后設計和制造車身和車輪,而是分別設計和制造發(fā)動機、底盤、車身和車輪,最后把它們組裝起來。這就是面向?qū)ο蟮幕舅悸?。客觀世界中任何ー個事物都可以看成一個對象。對象可以是自然物體,也可以是社會中的一種組織結(jié)構(gòu)(班級、系、學校)甚至ー個圖形、ー項計劃等都可以看成對象。復雜的對象由簡單的對象組成,例如火車站對象包含售票處、行李房、候車室和站臺、信號燈、鐵軌和通信設施等對象。對象是構(gòu)成系統(tǒng)的基本單位。任何ー個對象都具有靜態(tài)和動態(tài)的特征,班級這個對象具有從屬ー個系和專業(yè)、學生人數(shù)、組建時間等靜態(tài)特征,它還具有出操、學習、參加運動會等動態(tài)特征。靜態(tài)特征稱為屬性,動態(tài)特征稱為行為,外界給對象發(fā)出的信息一般稱作消息ー個對象往往包含ー組屬性和一組行為。如電視機包括生產(chǎn)廠家、品牌、屏幕尺寸等是靜態(tài)特征,開機、關(guān)機、選擇頻道、調(diào)節(jié)音量、調(diào)節(jié)彩色等是動態(tài)特征。面向?qū)ο蟮某绦蛟O計在設計ー個系統(tǒng)時,首先要確定系統(tǒng)中包括哪些對象,要分別設計這些對象。在C++中,每個對象由數(shù)據(jù)和函數(shù)(操作代碼)兩部分組成。數(shù)據(jù)代表了屬性,函數(shù)是對數(shù)據(jù)操作的代碼,代表了行為。例如三條邊長是三角形的屬性,利用三條邊長計算三角形面積、輸出計算結(jié)果,實現(xiàn)這些操作的代碼就是對象的行為,在程序設計中又稱方法。調(diào)用對象中的函數(shù)就是向?qū)ο髠鬟fー個消息,要求對象執(zhí)行某個操作。封裝與信息隱蔽對ー個對象進行封裝處理,把它的一部分屬性和功能向外界屏蔽,從外面看不到這些屬性和功能。例如錄像機里有電路板和機械控制部件,由于有機殼的保護,在外面只看到ー個黑箱子,在它的表面有若干個按鍵。人們只需知道這些按鍵的功能即可操作錄像機。而不必知道錄象機的工作原理和系統(tǒng)結(jié)構(gòu)。在設計ー個對象時,要周密地考慮如何進行封裝,把不必讓外界知道的部分隱蔽起來。也就是說,把對象的內(nèi)部實現(xiàn)和外部行為分隔開來。封裝性是面向?qū)ο蟪绦蛟O計的一個重要特點,封裝在此有兩個含義:①把有關(guān)的數(shù)據(jù)和操作代碼封裝在一個對象中,形成程序中的一個基本單位,各個對象之間相互獨立,互不干擾。②把對象中的某些部分對外隱蔽,只留下與外界聯(lián)系的接口接收外界的消息,這種對外界隱蔽的做法稱為信息屏蔽。封裝把對象內(nèi)部實現(xiàn)與外部分隔開,外界不了解對象內(nèi)部的具體細節(jié),其實外界也不需要了解。外界需要真正了解的是對象的對外接口。C++對象中的公有函數(shù)就是對象的對外接口。外界通過調(diào)用公有函數(shù),訪問對象中的數(shù)據(jù)成員,完成指定的操作。抽象抽象是表示同一類事物本質(zhì)的方法,它關(guān)注事物本質(zhì)特征,對象是具體的,例如某學院2006級計算機軟件專業(yè)的ー個學生是ー個對象,可以將一組同類對象的共同特征抽象出來,從而形成類的概念??梢詫⑶懊嫠岬哪硨W院2006級計算機軟件專業(yè)的所有學生可抽象出2006級計算機軟件專業(yè)學生類。類是對象的抽象,而對象是類的具體實例。繼承與重用如果已經(jīng)建立名為A的類,現(xiàn)要建立一個名為B的類,而B類與A類的內(nèi)容基本相同,只是在A類基礎上增加了一些屬性和行為,這樣只需在A類的基礎上添加新內(nèi)容即可,這就是面向?qū)ο蟪绦蛟O計中的繼承機制。C++也具有繼承機制,利用這個機制可以在一個已有的類的基礎上建立一個新類,這也是軟件重用思想,不僅可以利用自己過去建立的類,而且還可以利用其他人放在類庫中的類建立類,這就大大縮短了軟件開發(fā)周期。多態(tài)性多個相似而不完全相同的對象,收到外界給的同一個消息時,它們各自執(zhí)行不同的操作,這種現(xiàn)象叫多態(tài)現(xiàn)象。例如在windows中,用鼠標雙擊ー個文件對象時,如果它是可執(zhí)行文件則會執(zhí)行文件中的程序,如果它是ー個文本文件則會啟動ー個編輯器來打開這個文件,這就是面向?qū)ο蟪绦蛟O計中的多態(tài)性一個實際例子。在C++中所謂多態(tài)性是指:由繼承而產(chǎn)生的新類,它的對象對同一個消息會作出不同的響應。面向?qū)ο蟪绦蛟O計的特點傳統(tǒng)的面向過程程序設計是圍繞功能進行的,用ー個函數(shù)實現(xiàn)一個功能,ー個函數(shù)可以使用任何ー組數(shù)據(jù),ー組數(shù)據(jù)可以被多個函數(shù)使用。當程序規(guī)模越來越大,數(shù)據(jù)越來越多,操作越來越復雜,這種方法容易出現(xiàn)錯誤,程序員往往感到難以應付。面向?qū)ο蟪绦蛟O計采用的是另外一種思路。它面對的是一個個對象。實際上每組數(shù)據(jù)都有特定的用途,它是某種操作的對象。也就是說,ー組操作調(diào)用ー組數(shù)據(jù)。例如三角形的三條邊長q、b、c它們只與計算該三角形的面積、三角形的周長等操作有關(guān),與其他操作無關(guān)。我們把這三個數(shù)據(jù)和計算三角形面積、周長等操作的代碼放在ー起,封裝成一個對象,與外界相對分隔。這也符合客觀世界的本來面目。面向?qū)ο蟪绦蛟O計包括兩個方面:②設計所需的各種類,即決定把哪些數(shù)據(jù)和操作封裝在一起。②考慮怎樣向?qū)ο蟀l(fā)送消息(調(diào)用對象的成員函數(shù)),實現(xiàn)所需的操作。這時設計程序象一個總調(diào)度,不斷地向各個對象發(fā)送消息(命令),讓這些對象活動起來(激活這些對象),完成各自的職責范圍工作,各個對象的操作完成,整體任務也就完成了。2.1.2 類和對象作用類是C++中十分重要的概念,它是實現(xiàn)面向?qū)ο蟪绦蛟O計的基礎。C++對C改進,其中最重要的就是增加了類這樣ー種類型。類是所有面向?qū)ο蟮恼Z言的共同特征,所有面向?qū)ο蟮恼Z言都提供了這種類型。ー個有一定規(guī)模的C++程序是由許多類構(gòu)成的??梢哉f類是C++的靈魂。C++支持面向過程的程序設計,也支持基于對象和面向?qū)ο蟮某绦蛟O計。從本章到第四章介紹基于對象的程序設計。包括類和對象的概念、類的機制和聲明、對象的定義與使用等。這是面向?qū)ο蟪绦蛟O計的基礎。在面向過程的結(jié)構(gòu)化程序設計中,人們用下面的公式描述程序:程序=數(shù)據(jù)結(jié)構(gòu)+算法算法和數(shù)據(jù)結(jié)構(gòu)兩者是相互獨立的,是分開設計的。面向過程的程序設計是以數(shù)據(jù)結(jié)構(gòu)為基礎的算法設計.在實踐中人們逐漸認識到算法和數(shù)據(jù)結(jié)構(gòu)是互相緊密聯(lián)系不可分的。應當以ー個算法對應ー組數(shù)據(jù)結(jié)構(gòu),而不宜提倡一個算法對應多組數(shù)據(jù)結(jié)構(gòu),以及以ー組數(shù)據(jù)結(jié)構(gòu)對應多個算法。基于對象和面向?qū)ο蟪绦蛟O計
就是把ー個算法和一組數(shù)據(jù)結(jié)構(gòu)封裝在ー個對象中,形成了新的觀念:面向?qū)ο蟮能浖_發(fā)對象=數(shù)據(jù)結(jié)構(gòu)+算法程序=(對象+對象+…+對象)+消息消息的作用就是對對象進行控制。程序設計的關(guān)鍵是設計好每個對象,以及確定向這些對象發(fā)出的命令,讓各個對象完成相應的任務。Class類名Class類名{private:私有成員聲明public:公有成員聲明protected:保護成員聲明class是保留字,聲明類類型類名:按標識符取名。private,public、protected也是保留字,是成員訪問限定符,其后必須跟冒號。在類聲明的}后如不直接定義對象就必須跟分號。令private:只能被本類中的成員函數(shù)訪問,類外(除友元外)不能訪問。令public:公有成員可以被本類的成員函數(shù)訪問,也能在類的作用域范圍內(nèi)的其他函數(shù)訪問。令protected:受保護成員可由本類的成員函數(shù)訪問,也能由派生類的成員函數(shù)訪問。在定義類時,這三類成員不分前后順序,也可以重復出現(xiàn)。一般推薦最多出現(xiàn)一次類的成員函數(shù)在聲明類時,必須定義了訪問類數(shù)據(jù)成員的函數(shù),稱之類的成員函數(shù)。類成員函數(shù)是函數(shù)中的ー種,成員函數(shù)可以訪問本類中的所有成員。如果成員函數(shù)的成員訪問限定符是public,則對象可以通過它訪問類的其他成員;如果是private或protected,則對象不能用來訪問類的其他成員。一般方法是把需要與外界溝通的成員函數(shù)指定為public,作為類與外界的接ロC++允許在類內(nèi)聲明成員函數(shù)的原型,然后在類外定義成員函數(shù)。格式類型類名::函數(shù)名(形參表)(成員聲明)ExampleClassstudent{ intnum;stringname;charsex;public:void setdata()voiddisplay!));voidstudent::setdata()〃實現(xiàn){cin?num;cin?name;cin?sex;}voidstudent::display?!睂崿F(xiàn){cout?num?endl;cout?name?endl;cout?sex?endl;}studentstl,st2;在類外定義成員函數(shù)時,必須在函數(shù)中增加類名,用于限定它屬于哪個類,::是作用域限定符或稱作用域運算符。上面的例子中如果函數(shù)不用成員訪問限定符,函數(shù)就成了全局作用域中的display函數(shù)而不是成員函數(shù)。如果在::前不帶類名,或函數(shù)名前既無類名又無作用域運算符::,表示該函數(shù)是全局函數(shù)。inline成員函數(shù)C++默認在類內(nèi)定義的成員函數(shù)是inline函數(shù),如果在類外定義成員函數(shù)時,系統(tǒng)默認不把它當作inline成員函數(shù),此時必須在聲明函數(shù)時在函數(shù)前加inline關(guān)鍵字。在下面的例子中在函數(shù)聲明里,函數(shù)頭未加inline,C++將把它當作非inline函數(shù)Classstudent{intnum;stringname;charsex;public:voidsetdata()voiddisplay!)};voidstudent::setdataf){cin?num;cin?name;cin?sex;}voidstudent::display!){cout?num?endl;cout?name?endl;cout?sex?endl;}studentstl,st2;如果要把它作為inline函數(shù),只需在函數(shù)聲明時,在函數(shù)頭增加關(guān)鍵字inline。classstudent{ intnum;stringname;charsex;public:inlinevoid setdataf)inlinevoid display!)};對象成員的引用定義了對象后,在程序中可以直接訪問對象中的公有成員,它們可以是數(shù)據(jù)成員,也可以是成員函數(shù)。在程序中訪問對象成員有三種方法。用對象名和成員運算符訪問成員格式:對象名.成員名例:stl.display。;/Z調(diào)用成員函數(shù)display。; /Z調(diào)用普通函數(shù)注意:只有成員函數(shù)可以訪問類中的所有成員,而在類外只能訪問公有成員。如果在類外面用下面的語句是錯誤的:stl.num=10101用指向?qū)ο蟮闹羔樤L問成員可以通過指針訪問對象中的成員。classTime(public:inthour;intminute;};Timet,*p;p=&t;cout?p->hour?endl;p->hour表示p當前指向?qū)ο髏中的成員hour,此時(*p).hour也代表對象t中的成員hour,在這個例子中,p->hour、(*p).hour、t.hour三種表示是一個意思。用對象的引用訪問成員如果為ー個對象A定義ー個引用B,B是對象A的別名,A和B都是ー個對象,所以完全可以通過引用訪問對象中的成員。Timefl;Time&t2=tl;cout?t2.hour;這里t2是tl的別名,所以訪問t2.hour就是訪問tl.hour。#include<iostream>usingnamespacestd;classTime{public:inthour;intminute;ntsec;};intmain(){Timetl;Time&t2=tl;cin?t2.hour;cin?t2.minute;cin?tl.sec;cout?tl.hour?":"?tl,minute?":"?t2.sec?endl;}注意:必須在引用成員之前加對象名而不是類名。數(shù)據(jù)成員必須有初始值后才能訪問,否則它們的值是不可預知的。#include<iostream>usingnamespacestd;classTime{public:inthour;intminute;intsec;};intmain()(Timetl;cin?tl.hour?tl,minute?tl.sec;cout?tl.hour?":"?tl.minute?":"?tl.seccout?endl;Timet2;cin?t2.hour?t2.minute?t2.sec;cout?t2.hour?":"?t2.minute?":"?t2.seccout?endl;return0;}上面的例子中只有兩個對象就顯得有些繁瑣,為了解決這個問題,可以在主函數(shù)中定義輸入輸出函數(shù)進行輸入和輸出。(2)程序(b)#include<iostream>usingnamespacestd;classTime{public:inthour;intminute;intsec;);intmain(){voidset_time(Time&);//使用引用形參voidshow_time(Time&);Timetl;set_time(tl);show_time(tl);Timet2;set_time(t2);show_time(t2);return0;)voidset_time(Time&t)〃函數(shù)的實現(xiàn)cin?t.hour;cin?t.minute;cin?t.sec;)voidshow_time(Time&t)(cout?t.hour?":"<<t.minute?":"?t.sec?endl;)例2.3用成員函數(shù)處惠,入?出#include<iostream>usingnamespacestd;classTime{public:voidset_time();voidshow_time();private:inthour;intminute;intsec;};intmain()Timetl;tl.set_time();tl,show_time();Timet2;t2.set_time();t2.show_time();return0;)voidTime::set_time(){cin?hour;cin?minute;cin?sec;}voidTime::show_time()(cout?hour?":"?minute?":"?sec?endl;}例2.4在豊總效期中找?大值〃類定義#include<iostream>usingnamespacestd;classArray_max{public:voidset_value();voidmax_value();voidshow_value();private:intarray[10];intmax;);〃類體外,類函數(shù)的實現(xiàn);voidArray_max::set_value(){inti;for(i=0;i<10;i++)cin?array[i];}voidArray_max::max_value(){inti;max=array[0];for(i=l;i<10;i++)if(array[i]>max)max=array[i];voidArray_max::show_value(){cout?"max="?max;)/Z主函數(shù),驗證輸出infmain(){Array_maxarrmax;arrmax.set_value();arrmax.max_value();arrmax.show_value();return0;)類和對象的簡單應用類的封閉性和信息隱蔽實現(xiàn)公用接口與私有的分離C++通過類實現(xiàn)封裝性,類的作用就是把數(shù)據(jù)和關(guān)于操作數(shù)據(jù)的算法封裝在類類型中。在聲明類時,一般將數(shù)據(jù)成員指定為私有,使它們與外界隔離,把讓外界調(diào)用的成員函數(shù)指定為公有,外界通過公有函數(shù)實現(xiàn)對數(shù)據(jù)成員的訪問。外界與對象的唯一聯(lián)系就是調(diào)用公有成員函數(shù)。公有成員函數(shù)是用戶使用類的公用接口。用戶可以調(diào)用公有成員函數(shù)實現(xiàn)某些功能,用戶也只要了解每個公有成員函數(shù)的功能,不必了解這些功能是怎樣實現(xiàn)的,這就是接口與實現(xiàn)分離。為了防止用戶任意修改公有成員函數(shù),從而改變對數(shù)據(jù)的操作,往往不讓用戶看到公有成員函數(shù)源代碼。類中的數(shù)據(jù)是私有的,實現(xiàn)數(shù)據(jù)操作的細節(jié)對用戶是隱蔽的這種實現(xiàn)稱為私有實現(xiàn)這種類的公有接口與私有實現(xiàn)的分離形成了信息隱蔽。信息隱蔽的長處是:如果想修改或擴充類的功能,只需修改類中有關(guān)的數(shù)據(jù)成員和成員函數(shù),類外的部分不用修改。例如,在2.2.3節(jié)聲明的student類中增加數(shù)據(jù)成員年齡,可以這樣修改:Classstudent{intnum;stringname;intage:/Z 新增加的數(shù)據(jù)成員charsex;pubIic:voidsetdata()voiddisplay());voidstudent::setdata(){cin?num?name;cin?age?sex:
)voidstudent::display(){cout?num?endl?name?endl;cout?age?endI?sex?endl;)studentst1,st2;當接口與實現(xiàn)(對數(shù)據(jù)的操作)分離時,只要類的接口沒有改變,對私有實現(xiàn)的修改不會影響程序的其他部分。如果在編譯時發(fā)現(xiàn)類中的數(shù)據(jù)讀寫有錯,不必檢查整個程序,只需檢查本類中訪問這些數(shù)據(jù)的成員函數(shù)。這就使得程序(尤其是大程序)的設計、修改和調(diào)試變得方便和簡單了。面向?qū)ο蟪绦蜷_發(fā)時,一般將類的聲明(包括成員函數(shù)的聲明)放在指定的頭文件中,在程序中只要把有關(guān)的頭文件包含進來即可。不必在程序中重復寫類的聲明。還有一種方法是把類成員函數(shù)不定義在頭文件中,而另外放在ー個文件中。*****.h&&*****.cpp成員函數(shù)定義義件student.cppmain.obj主模塊main.cppstudent.objmam.exe成員函數(shù)定義義件student.cppmain.obj主模塊main.cppstudent.objmam.exe//student.h 這是頭文件在此聲明類classstudent{intnum;charname[10];charsex;public:voidsetdata();voiddisplay!);};//student.cpp#include<iostream>#include"student.h"usingnamespacestd;voidstudent::setdata()cin?num;cin?name;cin?sex;}voidstudent::display!)cout?num?endl;cout?name?endl;cout?sex?endl;}〃寫主函數(shù)調(diào)用實現(xiàn)的類:#include<iostream>#include"student.h"usingnamespacestd;intmain(){studentstl;stl.setdata();stl.display!);return0;}這個程序包含了三個文件,一個是主模塊main.cpp,一個是student.cpp。在預編譯時會將頭文件student.h中內(nèi)容取代#include"student.h"行??梢园磳Χ鄠€文件程序的編譯和運行方法對程序進行編譯和連接。C++編譯系統(tǒng)對兩個.cpp文件分別進行編譯,得到兩個.。bj文件,然后將它們和其他系統(tǒng)資源連接起來,形成可執(zhí)行文件main.exe??梢圆槐孛看螌tudent.cpp進行編譯,把第一次編譯后形成的目標文件保存起來,以后在需要時把它調(diào)出來直接與程序的目標文件相連即可。這和使用函數(shù)庫中的函數(shù)是類似的。在實際中,將若干個常用的功能相近的類聲明集中在一起,形成類庫。類庫包括C++編譯系統(tǒng)提供的標準類庫,用戶的類庫。類庫有兩個組成部分:(1)類聲明頭文件(2)經(jīng)過編譯的成員函數(shù)的定義,它是目標文件。用戶只要把類庫裝入C++編譯系統(tǒng)所在的子目錄中,并在程序中用include命令把類聲明的頭文件包括到程序中,就能使用這些類和其中的成員函數(shù)。類聲明和成員函數(shù)定義分離面向?qū)ο蟪绦蛟O計中的幾個名詞類的成員函數(shù)在面向?qū)ο蟪绦蚶碚撝杏址Q為方法,方法是指對數(shù)據(jù)的操作。只有被聲明為公有的方法(成員函數(shù))才能被對象外界所激活。外界是通過發(fā)消息激活有關(guān)的方法。所謂消息其實就是一條命令,由程序語句實現(xiàn)。如stl.displayf);是向?qū)ο髎t!發(fā)出ー個消息,讓它執(zhí)行display方法,這里,stl是對象,display!)是方法,語句stl.display。;是消息。Chapters關(guān)于類和對象的進一步討論構(gòu)造函數(shù)如果定義ー個變量,而程序未對其進行初始化的話,這個變量的值是不確定的,因為C和C++不會自覺地去為它賦值。與此相似,如果定義ー個對象,而程序未對其數(shù)據(jù)成員進行初始化的話,這個對象的值也是不確定的。對象的初始化在定義ー個類時,不能對其數(shù)據(jù)成員賦初值,因為類是ー種類型,系統(tǒng)不會為它分配內(nèi)存空間。在建立一個對象時,需要對其數(shù)據(jù)成員賦初值。如果ー個數(shù)據(jù)成員未被賦初值,則它的值是不確定的。因為系統(tǒng)為對象分配內(nèi)存時,保持了內(nèi)存單元的原狀,它就成為數(shù)據(jù)成員的初值。這個值是隨機的。C++提供了構(gòu)造函數(shù)機制,用來為對象的數(shù)據(jù)成員進行初始化。在前面的學習中一直未講這個概念,其實如果你未設計構(gòu)造函數(shù),系統(tǒng)在創(chuàng)建對象時,會自動提供ー個默認的構(gòu)造函數(shù),而它只為對象分配內(nèi)存空間其他什么也不做。如果類中的所有數(shù)據(jù)成員是公有的,可以在定義對象時對其數(shù)據(jù)成員初始化。例如:classTime{public:inthour;intminute;intsec;);Timetl{15,36,26);在一個大括號內(nèi)順序列出各個公有數(shù)據(jù)成員的值,在兩個值之間用逗號分隔。注意這只能用于數(shù)據(jù)成員都是公有的情況。在前面的例子里,是用成員函數(shù)對對象的數(shù)據(jù)成員賦初值,如果一個類定義了多個對象,對每個對象都要調(diào)用成員函數(shù)對數(shù)據(jù)成員賦初值,那么程序就會變得煩瑣,所以用成員函數(shù)為數(shù)據(jù)成員賦初值絕不是ー個好方法。構(gòu)造函數(shù)用于為對象分配空間和進行初始化,它屬于某ー個類,可以由系統(tǒng)自動生成。也可以由程序員編寫,程序員根據(jù)初始化的要求設計構(gòu)造函數(shù)及函數(shù)參數(shù)。構(gòu)造函數(shù)是ー種特殊的成員函數(shù),在程序中不需要寫調(diào)用語句,在系統(tǒng)建立對象時由系統(tǒng)自覺調(diào)用執(zhí)行。構(gòu)造函數(shù)的特點:(1)構(gòu)造函數(shù)的名字與它的類名必須相同。(2)它沒有類型,與不返回值(3)它可以帶參數(shù),也可以不帶參數(shù)。例3.1在例2.3的基礎上定義構(gòu)造成員函數(shù)#include<iostream>usingnamespacestd;classTime{public:Timed{hour=0;minute=O;sec=O;}〃構(gòu)造函數(shù)voidset_time();voidshow_time();private:inthour;intminute;intsec;);intmain()(Timetl;tl,set_time();tl,show_time();Timet2;t2.show_time();return0;)voidTime::set_time(){cin?hour;cin?minute;cin?sec;}voidTime::show_time()(cout?hour?":"?ininute?":"?sec?endl;}在類Time中定義了構(gòu)造函數(shù)Time,它與所在的類同名。在建立對象時自動執(zhí)行構(gòu)造函數(shù),該函數(shù)的作用是為對象中的各個數(shù)據(jù)成員賦初值〇〇注意只有執(zhí)行構(gòu)造函數(shù)時オ為數(shù)據(jù)成員賦初值。程序運行時首先建立對象tl,并對tl中的數(shù)據(jù)成員賦初值〇,然后執(zhí)行tl.setjime函數(shù),從鍵盤輸入新值給對象tl的數(shù)據(jù)成員,再輸出tl的數(shù)據(jù)成員的值。接著建立對象t2,同時對t2中的數(shù)據(jù)成員賦初值〇,最后輸出t2的數(shù)據(jù)成員的初值。程序運行的情況為:10 255410:25:54 〃輸出tl的值0:0:0 〃輸出t2的值也可以在類內(nèi)聲明構(gòu)造函數(shù)然后在類外定義構(gòu)造函數(shù)。將程序修改為:Timed;然后在類外定義構(gòu)造函數(shù):Time::Time(){hour=0;minute=O;sec=O;令關(guān)于構(gòu)造函數(shù)的使用,說明如下:什么時候調(diào)用構(gòu)造函數(shù)呢?當函數(shù)執(zhí)行到對象定義語句時建立對象,此時就要調(diào)用構(gòu)造函數(shù),對象就有了自己的作用域,對象的生命周期開始了。構(gòu)造函數(shù)沒有返回值,因此不需要在定義中聲明類型。構(gòu)造函數(shù)不需要顯式地調(diào)用,構(gòu)造函數(shù)是在建立對象時由系統(tǒng)自動執(zhí)行的,且只執(zhí)行一次。構(gòu)造函數(shù)一般定義為public。在構(gòu)造函數(shù)中除了可以對數(shù)據(jù)成員賦初值,還可以使用其他語句。如果用戶沒有定義構(gòu)造函數(shù),C++系統(tǒng)會自動生成一個構(gòu)造函數(shù),而這個函數(shù)體是空的,不執(zhí)行初始化操作。構(gòu)造函數(shù)的作用帶參數(shù)的構(gòu)造函數(shù)可以采用帶參數(shù)的構(gòu)造函數(shù),在調(diào)用不同對象的構(gòu)造函數(shù)時,從外邊將不同的數(shù)據(jù)傳遞給構(gòu)造函數(shù),實現(xiàn)不同對象的初始化。構(gòu)造函數(shù)的首部的一般格式為:構(gòu)造函數(shù)名(類型形參1,類型形參2,???)在定義對象時指定實參,定義對象的格式為:類名對象名(實參1,實參2,…);例3.2有兩個長方柱,其長、寬、高分別為:12,25,3015,30,21編寫程序,在類中用帶參數(shù)的構(gòu)造函數(shù),計算它們的體積。分析:可以在類中定義一個計算長方體體積的成員函數(shù)計算對象的體積。#include<iostream>usingnamespacestd;classBox{public:Boxfint,intjnt);intvolumef);private:intheight;intwidth;Box::Box(inthjntwjntlen)/Z長方體構(gòu)造函數(shù){height=h;width=w;length=len;}intBox::volume()/Z計算長方體的體積{return(height*width*length);}intmain(){Boxboxl(12,25,30); 〃定義對象box1cout?"boxl體積="<<boxl.volumef)?endl;Boxbox2(15,30,21); 〃定義對象box2cout?"box2體積="?box2.volume()?endl;return0;}構(gòu)造函數(shù)Box有3個參數(shù),分別代表長、寬、高。在主函數(shù)中定義對象boxl時,指定了實參12,25,30。然后調(diào)用成員函數(shù)計算長方體的體積。程序運行的結(jié)果如下:box!體積=9000box2體積=9450提醒:⑴帶形參的構(gòu)造函數(shù)在定義對象時必須指定實參⑵用這種方法可以實現(xiàn)不同對象的初始化。用參數(shù)初始化表初始化數(shù)據(jù)成員令C++提供了參數(shù)初始化表的方法對數(shù)據(jù)成員初始化。這種方法不必在構(gòu)造函數(shù)內(nèi)對數(shù)據(jù)成員初始化,在函數(shù)的首部就能實現(xiàn)數(shù)據(jù)成員初始化。函數(shù)名(類型】形參1,類型2形參2):成員名1(形參1),成員名2(形參2){ )Example:Box::Box(inth,infw,intlen):height(h),width(w),length(len){}功能:執(zhí)行構(gòu)造函數(shù)時,將形參丨的值賦予成員丨,將形參2的值賦予成員2,形參的值由定義對象時的實參值決定。此時定義對象的格式依然是帶實參的形式:類名對象名(實參1,實參2);例:定義帶形參初始化表的構(gòu)造函數(shù)Box::Box(inth,intw,intlen):height(h),width(w),length(len){}定義對象:Boxboxl(12,25,30);Boxbox2(l5,30,21);構(gòu)造函數(shù)的重載構(gòu)造函數(shù)也可以重載。ー個類可以有多個同名構(gòu)造函數(shù),函數(shù)參數(shù)的個數(shù)、參數(shù)的類型各不相同。例3.3:在例3.2的基礎上定義兩個構(gòu)造函數(shù)其中一個無參數(shù),另ー個有參數(shù)。#include<iostream>usingnamespacestd;classBox{public:Box();Box(inth,intw,intlen):height(h),width(w),length(len){}intvolume();private:intheight;intwidth;);Box::Box(){height=10;width=10;length=10;)intBox::volume(){return(height*width*length);}intmain(){Boxboxl;cout?"boxl體積="?boxl.volume()?endl;Boxbox2(15,30,25);cout?"box2體積="?box2.volume()?endl;return0;}例子中定義了兩個構(gòu)造函數(shù),ー個無參數(shù)另ー個帶三個參數(shù)。系統(tǒng)根據(jù)定義對象的格式?jīng)Q定調(diào)用哪個構(gòu)造函數(shù)。對象boxl沒有實參系統(tǒng)為它調(diào)用無參數(shù)的構(gòu)造函數(shù);對象box2帶三個實參系統(tǒng)為它調(diào)用帶形參的構(gòu)造函數(shù)。說明:(1)不帶形參的構(gòu)造函數(shù)為默認構(gòu)造函數(shù)每個類只有一個默認構(gòu)造函數(shù),如果是系統(tǒng)自動給的默認構(gòu)造函數(shù),其函數(shù)體是空的。(2)雖然每個類可以包含多個構(gòu)造函數(shù),但是創(chuàng)建對象時,系統(tǒng)僅執(zhí)行其中一個。3.1.6 使用默認參數(shù)的構(gòu)造函數(shù)C++允許在構(gòu)造函數(shù)里為形參指定默認值,如果創(chuàng)建對象時,未給出相應的實參時,系統(tǒng)將用形參的默認值為形參賦值。格式:函數(shù)名(類型形參]=常數(shù),類型形參2=常數(shù),…);例3.4:將例3.3中的構(gòu)造函數(shù)改用帶默認值的參數(shù),長、寬、高的默認值都是10o#include<iostream>usingnamespacestd;classBox{public:Boxfintw=10,inth=10,intlen=10);intvolume();private:intheight;intwidth;intlength;);Box::Box(intwjnthjntlen){height=h;width=w;length=len;}intBox::volume(){return(height*width*length);}intmain()(Boxboxl;cout?"boxl體積="?boxl,volume()?endl;Boxbox2(15);cout?"box2體積"?box2.volume()?endl;Boxbox3(15,30);cout?"box3體積"?box3.volume()?endl;Boxbox4(15,30,20);cout?"box4體積”"box4.volume()<<endl;return0;}程序運行結(jié)果為:box!體積=1000box2體積=1500box3體積=4500box4體積=9000構(gòu)造函數(shù)也可以改寫成帶參數(shù)初始化表的形式:Box::Box(inth,intw,intlen):height(h),width(w),lengthflen){}整個函數(shù)只需一行,簡單方便。在構(gòu)造函數(shù)中使用默認參數(shù)提供了建立對象的多種選擇,它的作用相當于多個重載構(gòu)造函數(shù)。說明:(1)如果在類外定義構(gòu)造函數(shù),應該在聲明構(gòu)造函數(shù)時指定默認參數(shù)值,在定義函數(shù)時可以不再指定默認參數(shù)值。(2)在聲明構(gòu)造函數(shù)時,形參名可以省略例如:Boxfint=10,int=10,int=10);(3)如果構(gòu)造函數(shù)的所有形參都指定了默認值,在定義對象時,可以指定實參也可不指定實參。由丁一不指定實參也可以調(diào)用構(gòu)造函數(shù),因此全部形參都指定了默認值的構(gòu)造函數(shù)也屬于默認構(gòu)造函數(shù)。為了避免歧義,不允許同時定義不帶形參的構(gòu)造函數(shù)和全部形參都指定默認值的構(gòu)造函數(shù)。(4)同樣為了避免歧義性,如定義了全部形參帶默認值的構(gòu)造函數(shù)后,不能再定義重載構(gòu)造函數(shù)。反之亦然。Boxfint=10,int=10,int=10);Box();Box(int,int);若定義對象:Boxboxl;Boxbox2(15,30);這時應該調(diào)用哪個構(gòu)造函數(shù)呢?如果構(gòu)造函數(shù)中參數(shù)并非都帶默認值時,要具體分析情況。如有以下三個原型聲明:Box();Box(intjnt=10,int=10);Box(int,int);若定義對象:Boxboxl; /Z正確,調(diào)用第一個Boxbox2(15);/Z 調(diào)用第二個Boxbox3(15,30);/Z不知調(diào)用哪ー個因此不要同時使用重載構(gòu)造函數(shù)和帶默認值的構(gòu)造函數(shù)。析構(gòu)函數(shù)析構(gòu)函數(shù)也是個特殊的成員函數(shù),它的作用與構(gòu)造函數(shù)相反,當對象的生命周期結(jié)束時,系統(tǒng)自動調(diào)用析構(gòu)函數(shù),收回對象占用的內(nèi)存空間。執(zhí)行析構(gòu)函數(shù)的時機:①在ー個函數(shù)內(nèi)定義的對象,當這個函數(shù)結(jié)束時,自動執(zhí)行析構(gòu)函數(shù)釋放對象。②static局部對象要到main函數(shù)結(jié)束或執(zhí)行exit命令時オ自動執(zhí)行析構(gòu)函數(shù)釋放對象。③全局對象(在函數(shù)外定義的對象)當main函數(shù)結(jié)束或執(zhí)行exit命令時自動執(zhí)行析構(gòu)函數(shù)釋放對象。④如果用new建立動態(tài)對象,用delete時自動執(zhí)行析構(gòu)函數(shù)釋放對象。析構(gòu)函數(shù)的特征①析構(gòu)函數(shù)名以?符號開始后跟類名②析構(gòu)函數(shù)沒有數(shù)據(jù)類型、返回值、形參。由于沒有形參所以析構(gòu)函數(shù)不能重載。ー個類只有一個析構(gòu)函數(shù)。③如果程序員沒有定義析構(gòu)函數(shù),C++編譯系統(tǒng)會自動生成一個析構(gòu)函數(shù)。析構(gòu)函數(shù)除了釋放對象(資源)タト,還可以執(zhí)行程序員在最后一次使用對象后希望執(zhí)行的任何操作。例如輸出有關(guān)的信息。例3.5包含構(gòu)造函數(shù)和析構(gòu)函數(shù)的C++程序#include<iostream>#include<string>usingnamespacestd;classStudent{public:Student(intn,stringnam,chars){num=n;name=nam;sex=s;cout?"Constructorcalled."?endl;)~Student(){cout?"Destructorcalled."?endl;}voiddisplay!){cout?"num:"?num?endl;cout?"name:"?name?endl;cout<<"sex:"?sex?endl?endl;}private:infnum;stringname;charsex;};intmain(){Studentstudl(lOOlO/'Wangjr'f');stud1.display!);Studentstud2(1001l,"Zhang_fun",'m');stud2.display();return0;}main函數(shù)前聲明的類其作用域是全局的。程序運行結(jié)果如下:Constructorcalled.num;10010name:Wangjisex:fConstructorcalled.num:10011name:Zhang_funsex:mDestructorcalled.Destructorcalled.調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序在使用構(gòu)造函數(shù)和析構(gòu)函數(shù)時需要特別注意對它們的調(diào)用時間和調(diào)用順序。在一般情況下,調(diào)用析構(gòu)函數(shù)的次序與調(diào)用構(gòu)造函數(shù)的次序恰好相反:最先調(diào)用構(gòu)造函數(shù)的對象,最后調(diào)用析構(gòu)函數(shù)。而最后調(diào)用構(gòu)造函數(shù)的對象,最先調(diào)用析構(gòu)函數(shù)??珊営洖?先構(gòu)造的后析構(gòu),后構(gòu)造的先析構(gòu),它相當一個棧,后進先出。對象1構(gòu)造函數(shù) 〉對象2構(gòu)造函數(shù)ー〉對象2析構(gòu)函數(shù)一〉對象1析構(gòu)函數(shù)對象數(shù)組類是ー種特殊的數(shù)據(jù)類型,它當然是C++的合法類型,自然就可以定義對象數(shù)組。在ー個對象數(shù)組中各個元素都是同類對象例如一個班級有50個學生,每個學生具有學號、年齡、成績等屬性,可以為這個班級建立一個對象數(shù)組,數(shù)組包括了50個元素:studentstd[50];可以這樣建立構(gòu)造函數(shù):student::student(int=1001,int=18jnt=60);在建立數(shù)組時,同樣要調(diào)用構(gòu)造函數(shù)。上面的數(shù)組有50個元素,要調(diào)用50次構(gòu)造函數(shù)。如果構(gòu)造函數(shù)有多個參數(shù),C++要求:在等號后的花括號中為每個對象分別寫出構(gòu)造函數(shù)并指定實參。格式為:studentst[n]={student(實參1,實參2,實參3); 、…… 卜n個對象student(實參1,實參2,實參3);J};對象指針指針的含義是內(nèi)存單元的地址,可以指向一般的變量,也可以指向?qū)ο?。指向?qū)ο蟮闹羔槍ο笠紦?jù)一片連續(xù)的內(nèi)存空間,CPU實際都是按地址訪問內(nèi)存,所以對象在內(nèi)存的起始地址是CPU確定對象在內(nèi)存中位置的依據(jù)。這個起始地址稱為對象指針。C++的對象也可以參加取地址運算.&對象名運算的結(jié)果是該對象的起始地址,也稱對象的指針。要用與對象類型相同的指針變量保存運算的結(jié)果。C++中定義對象的指針變量與定義其他的指針變量相似,格式如下:類名?變量名表類名表示對象所屬的類。變量名按標識符規(guī)則取名,兩個變量名之間用逗號分隔。定義好指針變量后,必須先給賦予合法的地址后才能使用。例如定義ー個類:classTime{public:Time(){hour=0;minute=O;sec=O;)voidset_time();voidshow_time();private:inthour;intminute;intsec;);voidTime::set_time(){cin?hour;cin?minute;cin?sec;}voidTime::show_time(){cout?hour?":"?minute?":"?sec?endl;)在此基礎上,有以下語句:Time*pt;〃定義pt是指向!ime類對象的指針Timetl;//定義Time類對象tlpt=&tl;//將對象tl的地址賦予pt程序在此之后就可以用指針變量訪問對象的成員。(*pt).hourpt->hour(*pt).show_time()pt->show_tiirie()指向?qū)ο蟪蓡T的指針對象由成員組成。對象占據(jù)的內(nèi)存區(qū)是各個數(shù)據(jù)成員占據(jù)的內(nèi)存區(qū)的總和。對象成員也有地址,即指針。這指針分指向數(shù)據(jù)成員的指針和指向成員函數(shù)的指針..指向?qū)ο蠊袛?shù)據(jù)成員的指針①定義數(shù)據(jù)成員的指針變量數(shù)據(jù)類型?指針變量名②計算公有數(shù)據(jù)成員的地址&對象名?成員名這里的數(shù)據(jù)類型是數(shù)據(jù)成員的數(shù)據(jù)類型。例:Timetl;int*pl;//定義ー個指向整型數(shù)據(jù)的指針變量pl=&tl.hour;//假定hour是公有成員cout?*pl?endl;.指向?qū)ο蟪蓡T函數(shù)的指針①定義指向成員函數(shù)的指針變量數(shù)據(jù)類型(類名::?變量名)(形參表);數(shù)據(jù)類型是成員函數(shù)的類型。類名是對象所屬的類變量名按標識符取名形參表:指定成員函數(shù)的形參表(形參個數(shù)、類型)②取成員函數(shù)的地址&類名::成員函數(shù)名在VC++系統(tǒng)中,也可以不寫&。為了與C語言一致,建議不要省略&。③給指針變量賦初值指針變量名=&類名::成員函數(shù)名;④用指針變量調(diào)用成員函數(shù)(對象名??指針變量名)([實參表]);對象名:是指定調(diào)用成員函數(shù)的對象。*:明確其后的是ー個指針變量。實參表:與成員函數(shù)的形參表對應,如無形參,可以省略實參表。例3.7有關(guān)對象指針的使用方法〃類定義#include<iostream>usingnamespacestd;classTime{public:Time(int,intint);inthour;intminute;intsec;voidget_time(););/Z類函數(shù)的實現(xiàn)Time::Time(inthjntmjnts){hour=h;minute=m;sec=s;)voidTime::get_time(){cout?hour?":"?minute?":"?sec?endl;}intmain(){Timetl(10,13,56);intmain(){Timetl(10,13,56);int*pl=&tl.hour;//cout?*pl?endl;tl.get_time();//Time*p2=&tl; //p2->get_time(); //void(Time::*p3)();//p3=&Time::get_time;//定義指向成員的指針pl調(diào)用成員函數(shù)定義指向?qū)ο髏l的指針p2用對象指針調(diào)用成員函數(shù)定義指向成員函數(shù)的指針給成員函數(shù)的指針賦值(tl.*p3)();/Z用指向成員函數(shù)的指針調(diào)用成員函數(shù)return0;)程序運行結(jié)果為:10 〃?pl的值10:13:56 // tl.get_time();的執(zhí)行結(jié)果10:13:56 // p2->get_time();的執(zhí)行結(jié)果10:13:56 // (tl.*p3)():的執(zhí)行結(jié)果程序采用了三種方法輸出t!的hour,minute,sec的值說明:(1)成員函數(shù)的起始地址的正確表示是&類名::成員函數(shù)名。不要寫成:p3=&tl.get_time;(2)主函數(shù)的第8和9行可以合并寫成:void(Time::*p3)=&Time::get_time;3.5.3this指針一個類的成員函數(shù)只有一個內(nèi)存拷貝。類中不論哪個對象調(diào)用某個成員函數(shù),調(diào)用的都是內(nèi)存中同一個成員函數(shù)代碼。例如Time類一個成員函數(shù):voidTime::get_time(){cout?hour?":"?minute?":"?sec?endl;}tl.get_time();t2.get_time();當不同對象的成員函數(shù)訪問數(shù)據(jù)成員時,怎么保證訪問的就是指定對象的數(shù)據(jù)成員?其實每個成員函數(shù)中都包含ー個特殊的指針,它的名字是this〇它是指向本類對象的指針,當對象調(diào)用成員函數(shù)時,它的值就是該對象的起始地址。所以為了區(qū)分不同對象訪問成員函數(shù),語法要求的調(diào)用成員函數(shù)的格式是:對象名.成員函數(shù)名(實參表)從語法上明確是對象名所指的對象調(diào)用成員函數(shù)。This指針是隱式使用的,在調(diào)用成員函數(shù)時C++把對象的地址作為實參傳遞給this指針。例如成員函數(shù)定義如下:intBox::volumef){return(height*width*length);}C++編譯成:intBox::volumef*this){return(this->height*this->width*this->length);}對于計算長方體體積的成員函數(shù)volume,當對象a調(diào)用它時,就把對象a地址給this指針,編譯程序?qū)的地址作為實參調(diào)用成員函數(shù):a.volume(&a);實際上函數(shù)是計算:(this->height)*(this->width)*(this->length)這時就等價計算(a.height)*(a.width)*(a.length)可以用(*this)表示調(diào)用成員函數(shù)的對象。(*this)就是this所指的對象。如前面的計算長方體體積的函數(shù)中return語句可以寫成:return((*this).height*(*this).width*(*this).length);注意this兩側(cè)的括號不能省略,不能寫成:return(*this.height**this.width**this.length);根據(jù)運算符優(yōu)先級語句被翻譯成:*(this.height),而this.height是非法的,編譯將報錯。C++通過編譯程序,在對象調(diào)用成員函數(shù)時,把對象的地址賦予this指針,用this指針指向?qū)ο?,實現(xiàn)了用同一個成員函數(shù)訪問不同對象的數(shù)據(jù)成員。共用數(shù)據(jù)的保護如果即希望數(shù)據(jù)在一定范圍內(nèi)共享,又不愿它被隨意修改,從技術(shù)上可以把數(shù)據(jù)指定為只讀型的。C++提供const手段,將數(shù)據(jù)、對象、成員函數(shù)指定為常量,從而實現(xiàn)了只讀要求,達到保護數(shù)據(jù)的目的。常對象定義格式:const類名對象名(實參表);或: 類名const對象名(實參表);把對象定義為常對象,對象中的數(shù)據(jù)成員就是常變量,在定義時必須帶實參作為數(shù)據(jù)成員的初值,在程序中不允許修改常對象的數(shù)據(jù)成員值。如果ー個常對象的成員函數(shù)未被定義為常成員函數(shù)(除構(gòu)造函數(shù)和析構(gòu)函數(shù)外),則對象不能調(diào)用這樣的成員函數(shù)。如: constTimetl(10,15,36);tl.get_time();/Z錯誤,不能調(diào)用為了訪問常對象中的數(shù)據(jù)成員,要定義常成員函數(shù):voidget_time()const如果在常對象中要修改某個數(shù)據(jù)成員,C++提供了指定可變的數(shù)據(jù)成員方法。格式:mutable類型數(shù)據(jù)成員;在定義數(shù)據(jù)成員時加mutable后,將數(shù)據(jù)成員聲明為可變的數(shù)據(jù)成員,就可以用聲明為const的成員函數(shù)修改它的值。常對象成員可以在聲明普通對象時將數(shù)據(jù)成員或成員函數(shù)聲明為常數(shù)據(jù)成員或常成員函數(shù)。格式:const類型數(shù)據(jù)成員名將類中的數(shù)據(jù)成員定義為具有只讀的性質(zhì)。注意只能通過帶參數(shù)初始表的構(gòu)造函數(shù)對常數(shù)據(jù)成員進行初始化。例: constinthour;Time::Time(inth){hour=h;???}/Z錯誤應該寫成:Time::Time(inth):hour(h){}在類中聲明了某個常數(shù)據(jù)成員后,該類中每個對象的這個數(shù)據(jù)成員的值都是只讀的,而每個對象的這個數(shù)據(jù)成員的值可以不同,由定義對象時給出。常成員函數(shù)定義格式:類型函數(shù)名 (形參表)constconst是函數(shù)類型的一部分,在聲明函數(shù)原型和定義函數(shù)時都要用const關(guān)鍵字。常成員函數(shù)不能修改對象的數(shù)據(jù)成員,也不能調(diào)用該類中沒有由關(guān)鍵字const修飾的成員函數(shù),從而保證了在常成員函數(shù)中不會修改數(shù)據(jù)成員的值。如果ー個對象被說明為常對象,則通過該對象只能調(diào)用它的常成員函數(shù)。指向?qū)ο蟮某V羔樔绻诙x指向?qū)ο蟮闹羔槙r,使用了關(guān)鍵字const,它就是ー個常指針,必須在定義時對其初始化。并且在程序運行中不能再修改指針的值。類名*const指針變量名=對象地址例:Timetl(10,12,15),t2;Time*constpl=&tl;在此后,程序中不能修改pl。例:Time*constpl=&t2;/Z錯誤語句指向?qū)ο蟮某V羔?在程序運行中始終指的是同一個對象。即指針變量的值始終不變,但它所指對象的數(shù)據(jù)成員值可以修改。當需要將一個指針變量固定地與一個對象相聯(lián)系時,就可將指針變量指定為const。往往用常指針作為函數(shù)的形參,目的是不允許在函數(shù)中修改指針變量的值,讓它始終指向原來的對象。前面學過引用是傳遞參數(shù)的有效辦法。用引用形參時,形參變量與實參變量是同ー個變量,在函數(shù)內(nèi)修改引用形參也就是修改實參變量,如果用引用形參又不想讓函數(shù)修改實參,可以使用常引用機制。格式:const類名&形參對象名例3.8對象的引用#include<iostream>usingnamespacestd;classTime{public:Time(int,int,int);inthour;intminute;intsec;);Time::Time(inthjntmjnts){hour=h;minute=m;sec=s;)voidfun(Time&t){t.hour=18;}intmain(){Time11(10,13,56);fun(tl);cout?tl,hour?endl;return0;)#include<iostream>usingnamespacestd;classTime{public:Time(int,int,int);voidfun(int&t)hour=t;t=18;如果用引用形參又不想讓函數(shù)修改實參,可以使用常引用機制。#include<iostream>usingnamespacestd;classTime{public:Time(int,int,int);voidfun(int&t){hour=t;t=18;)inthour;intminute;intsec;):Time::Time(inthjntmjnts){hour=h;minute=m;sec=s;)intmain(infargc,char*argv[])(intx=15;Timetl(l0,13,56);tl.fun岡;cout?tl,hour?endl;cout?x?endl;return0;}如不希望在函數(shù)中修改實參れ的值,可以將它定義為常引用。函數(shù)原型為:voidfun(constint&t);如果在函數(shù)里仍然要修改形參t,此時編譯程序就會報錯。指向常對象的指針變量對象的常引用const型數(shù)據(jù)小結(jié)表3.3形式含スTineconsttl;或constTimetl;tl是常對象,其值在任蝠況下都不親變vo:d「me::ftm()constfun是Time類中的常成員函數(shù),可以引用,但不能修改本類中的數(shù)制成員Tine*constp;P是指向Time對象的常指針/的值(即p斜狗)不能改變coistTime*p;P是指向Time類常對象的指針,其指向的類時象的值不頻過的頼變Tine&tl=t;。是Time類對氯的引用,加1指向同一段內(nèi)存空間對象的動態(tài)建立和釋放C++提供了new和delete運算符,實現(xiàn)動態(tài)分配、回收內(nèi)存。它們也可以用來動態(tài)建立對象和釋放對象。動態(tài)建立對象格式:new 類名;功能:在堆里分配內(nèi)存,建立指定類的ー個對象。如果分配成功,將返回動態(tài)對象的起始地址(指針);如不成功,返回〇。為了保存這個指針,必須事先建立以類名為類型的指針變量。格式:類名?指針變量名:例:Box*pt;pt=newBox;如分配內(nèi)存成功,就可以用指針變量pt訪問動態(tài)對象的數(shù)據(jù)成員。cout?pt->height;cout?pt->volumef);當不再需要使用動態(tài)對象時,必須用delete運算符釋放內(nèi)存。格式:delete指針變量指針變量里存放的是用new運算返回的指針對象的賦值和復制對象的賦值如果一個類定義了兩個或多個對象,則這些同類對象之間可以互相賦值。這里所指的對象的值含義是對象中所有數(shù)據(jù)成員的值。格式對象1=對象2;對象1、對象2都是已建立好的同類對象功能:將對象2值賦予對象1〇例3.9對象的賦值#include<iostream>usingnamespacestd;classBox{public:Box(int=1Ojnt=1Ojnt=l0);intvolume();private:intheight;intwidth;intlength;};Box::Box(inthjntwjntlen){height=h;width=w;length=len;}intBox::volume(){return(height*width*length);)intmain()(Boxboxl(15,30,25),box2;cout?"box!體積="?boxl.volume()?endl;box2=boxl;cout?"box2體積="?box2.volume()?endl;return0;)運行結(jié)果如下:box!體積=11250box2體積=11250說明:(1)對象的賦值只對數(shù)據(jù)成員操作。(2)數(shù)據(jù)成員中不能含有動態(tài)分配的數(shù)據(jù)成員。對象的復制對象賦值的前提是對象1和對象2是已經(jīng)建立的對象。C++還可以按照一個對象克隆出另ー個對象(從無到有)。這就是復制對象。復制對象是創(chuàng)建對象的另一種方法(以前學過的是定義對象)。創(chuàng)建對象必須調(diào)用構(gòu)造函數(shù),復制對象要調(diào)用復制構(gòu)造函數(shù)。以Box類為例,復制構(gòu)造函數(shù)的形式是:Box::Box(constBox&b){ height=b.height;width=b.width;length=b.length;}復制構(gòu)造函數(shù)只有一個參數(shù),這個參數(shù)是本類的對象,且采用引用對象形式,為了防止修改數(shù)據(jù),加const限制。構(gòu)造函數(shù)的內(nèi)容就是將實參對象的數(shù)據(jù)成員值賦予新對象對應的數(shù)據(jù)成員,如果程序中未定義復制構(gòu)造函數(shù),編譯系統(tǒng)將提供默認的復制構(gòu)造函數(shù),復制類中的數(shù)據(jù)成員。復制對象有兩種格式:(1)類名對象2(對象丨);按對象1復制對象2〇(2)類名對象2=對象1,對象3=對象1,…;按對象1復制對象2、對象3。例:用復制對象的方法創(chuàng)建Box類的對象(用默認復制構(gòu)造函#include"stdafx.h"#include<iostream>usingnamespacestd;classBox{public:Box(int=10zint=10zint=10);intvolume();private:intheight;intwidth;intlength;};Box::Box(inth,intw,intlen){height=h;width=w;length=len;}intBox::volume(){return(height*width*length);)intmain(intargc,char*argv[]){Boxboxl(15,30,25);cout<<Mboxl的體積=n<<boxl.volume()<<endl;//Boxbox2=boxlzbox3=box2;Boxbox2(boxl),box3(box2);cout<<Hbox2的體積=n<<box2.volume()<<endl;cout<<nbox3的體積="<<box3.volume()<<endl;return0;}程序執(zhí)行結(jié)果:box!的體積=11250box2的體積=11250box3的體積=11250在以下情況調(diào)用復制構(gòu)造函數(shù)(1)在程序里用復制對象格式創(chuàng)建對象。(2)當函數(shù)的參數(shù)是對象。調(diào)用函數(shù)時,需要將實參對象復制給形參對象,在此系統(tǒng)將調(diào)用復制構(gòu)造函數(shù)。例:voidfun(Boxb){??}intmain(){Boxboxl(12,15,18);fun(boxl);return0;)(3)在函數(shù)返回值是類的對象時,需要將函數(shù)里的對象復制ー個臨時對象當作函數(shù)值返回。例:Boxf()returnboxl;)intmain(){Boxbox2;box2=f();)靜態(tài)成員C++用const保護數(shù)據(jù)對象不被修改,在實際中還需要共享數(shù)據(jù),C++怎樣提供數(shù)據(jù)共享機制?C++靜態(tài)成員、友元實現(xiàn)對象之間、類之間的數(shù)據(jù)共享。靜態(tài)數(shù)據(jù)成員靜態(tài)數(shù)據(jù)成員定義格式:static類型數(shù)據(jù)成員名例:classBox{public:Box(int=lOjnt=1Ojnt=10);intvolume();private:staticintheight;intwidth;intlength;};靜態(tài)數(shù)據(jù)成員具有這樣的特性:設Box有n個對象boxl..boxno這n個對象的height成員在內(nèi)存中共享一個整型數(shù)據(jù)空間。如果某個對象修改了height成員的值,其他n-1個對象的height成員值也被改變。從而達到n
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 農(nóng)村土地買賣合同范本
- 農(nóng)村建筑施工合同范本
- 買賣冬蟲夏草合同范本
- 勘界測繪合同范例
- 再婚買房合同范本
- 個體簡易合同范本
- 包工安裝護欄合同范本
- 單位銷售崗位勞動合同范本
- 俱樂部裝修合同范本
- 養(yǎng)殖合作建設合同范本
- 云南省實驗教材信息技術(shù)三年級第一冊第13課PPT課件
- 交際德語教程第二版A1Studio[21] 課后習題參考答案
- 最新修改 班組安全管理建設--5831模式通用課件
- 氣割、電氣焊作業(yè)的應急救援預案
- 2018年柴油機大修工程量單
- 超級精美PPT模版美國經(jīng)典ppt模板(通用珍藏版2)
- 2022年“葉圣陶杯”全國中學生新作文大賽專用稿紙
- 中醫(yī)內(nèi)科方歌-八
- 氣動控制閥的定義分類及工作原理詳解
- 梯形練字格A4紙打印版
- 對丁達爾效應的研究
評論
0/150
提交評論