C++程序設(shè)計(jì)實(shí)踐教程(下)ppt.ppt_第1頁(yè)
C++程序設(shè)計(jì)實(shí)踐教程(下)ppt.ppt_第2頁(yè)
C++程序設(shè)計(jì)實(shí)踐教程(下)ppt.ppt_第3頁(yè)
C++程序設(shè)計(jì)實(shí)踐教程(下)ppt.ppt_第4頁(yè)
C++程序設(shè)計(jì)實(shí)踐教程(下)ppt.ppt_第5頁(yè)
已閱讀5頁(yè),還剩253頁(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)介

1、C+程序設(shè)計(jì)實(shí)踐教程(下),第11章 類和對(duì)象,11.1 面向?qū)ο蟮乃枷?11.2 面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn) 11.3 面向?qū)ο筌浖_發(fā)的基本過(guò)程 11.4 類和對(duì)象 11.5 構(gòu)造函數(shù)與析構(gòu)函數(shù) 11.6 友元 11.7 靜態(tài)成員 11.8 const對(duì)象和成員函數(shù) 11.9 應(yīng)用實(shí)例 作業(yè):10,13,14,15,11.1 面向?qū)ο蟮乃枷?什么是面向過(guò)程?什么是面向?qū)ο螅?兩種不同的思想、方法。 面向過(guò)程的程序設(shè)計(jì) 用傳統(tǒng)程序設(shè)計(jì)語(yǔ)言進(jìn)行程序設(shè)計(jì)時(shí),必須詳細(xì)地描述解題的過(guò)程。程序設(shè)計(jì)工作主要圍繞設(shè)計(jì)解題過(guò)程來(lái)進(jìn)行,這種傳統(tǒng)的程序設(shè)計(jì)方法稱為面向過(guò)程的程序設(shè)計(jì)。,面向過(guò)程程序設(shè)計(jì),特點(diǎn) 程

2、序處理數(shù)據(jù)的一系列過(guò)程; 數(shù)據(jù)與過(guò)程分離; 程序數(shù)據(jù)結(jié)構(gòu)算法 缺點(diǎn) 重用性差 維護(hù)困難,面向?qū)ο蟪绦蛟O(shè)計(jì),面向?qū)ο蟪绦蛟O(shè)計(jì):將面向?qū)ο蠓椒ㄓ糜诔绦蛟O(shè)計(jì)。 出發(fā)點(diǎn)與基本原則: 模擬人類習(xí)慣思維方式,使開發(fā)軟件的方法盡可能接近人類認(rèn)識(shí)世界解決問題的方法。 對(duì)象作為模塊,對(duì)象是對(duì)客觀事物的自然的、直接的抽象和模擬,包含了數(shù)據(jù)及對(duì)數(shù)據(jù)的操作。,11.2 面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn),封裝性 將描述對(duì)象的數(shù)據(jù)及處理這些數(shù)據(jù)的代碼集中起來(lái)放在對(duì)象內(nèi)部,對(duì)象成為獨(dú)立模塊。 繼承性 從已有類(稱為基類)派生出新類。 多態(tài)性 同一個(gè)名字代表不同、但相似的功能。,11.3 面向?qū)ο筌浖_發(fā)的基本過(guò)程,軟件危機(jī)促進(jìn)了

3、軟件工程的形成與發(fā)展。 軟件工程:用系統(tǒng)工程學(xué)的原理和方法管理軟件開發(fā)過(guò)程,開發(fā)過(guò)程分為分析、設(shè)計(jì)、編程、測(cè)試、維護(hù)等階段。 面向?qū)ο蟮能浖こ?分析:明確系統(tǒng)必須做什么。 設(shè)計(jì):明確軟件系統(tǒng)怎么做。 實(shí)現(xiàn):選用合適的面向?qū)ο缶幊陶Z(yǔ)言,實(shí)現(xiàn)設(shè)計(jì)階段描述的軟件系統(tǒng)的各個(gè)類模塊,并根據(jù)類的相互關(guān)系集成。 測(cè)試:發(fā)現(xiàn)軟件中的錯(cuò)誤。 維護(hù):在軟件交付用戶使用期間,對(duì)軟件所作的修改。,11.4 類和對(duì)象,在面向?qū)ο蟪绦蛟O(shè)計(jì)中,對(duì)象是構(gòu)成程序的模塊,即程序是由一組對(duì)象構(gòu)成的,對(duì)象之間通過(guò)消息分工協(xié)作,共同完成程序的功能。 類是面向?qū)ο蟪绦蛟O(shè)計(jì)的核心,是對(duì)具有相同屬性與行為的一組事物的抽象描述。利用類可以把

4、數(shù)據(jù)和對(duì)數(shù)據(jù)所做的操作組合成一個(gè)整體,實(shí)現(xiàn)對(duì)數(shù)據(jù)的封裝和隱藏。 類是用戶自定義的數(shù)據(jù)類型,是創(chuàng)建對(duì)象的模型。,11.4.1 類的定義,1格式,關(guān)鍵字,class 類名 成員1說(shuō)明; 成員2說(shuō)明; 成員n說(shuō)明; ;,類定義體,分號(hào)不可缺!,2類的組成成員 數(shù)據(jù)成員: 變量或?qū)ο?。其類型為?成員函數(shù) 對(duì)數(shù)據(jù)成員進(jìn)行操作。,例: class Circle private: int radius; public: void setRadius(int r) radius=r; double area( ) return 3.14*radius*radius; ;,數(shù)據(jù)成員,函數(shù)成員1,?,函數(shù)成員2

5、,在定義一個(gè)類時(shí),注意: 類只是一種自定義數(shù)據(jù)類型,類中任何成員數(shù)據(jù)均不能使用關(guān)鍵字extern、auto或register指定其存儲(chǔ)類型,也不能初始化。例如: class Circle int radius=5; /錯(cuò)誤 extern float pi; /錯(cuò)誤 /省略其它成員 ; 成員函數(shù)可直接使用類中的任一成員。 類類型與結(jié)構(gòu)體類型相似,結(jié)構(gòu)體類型也可有函數(shù)成員,差別在于,類類型的缺省訪問權(quán)限是private,結(jié)構(gòu)體類型的缺省訪問權(quán)限是public。,11.4.2 類成員的訪問控制,在定義類時(shí),指定其成員訪問權(quán)限的原則: 僅供該類的成員函數(shù)訪問的成員應(yīng)指定為私有的。 若定義的成員在派生類

6、中也需經(jīng)常使用,則應(yīng)指定其為保護(hù)的。 若允許在類外使用成員時(shí),應(yīng)將其訪問權(quán)限定義為公有的。,11.4.3 類的成員函數(shù)及重載,成員函數(shù)必須在類體內(nèi)給出原型說(shuō)明,至于它的實(shí)現(xiàn),可以放在類體內(nèi),也可以放在類體外。 當(dāng)成員函數(shù)所含代碼較少時(shí),一般直接在類中定義該成員函數(shù); 當(dāng)成員函數(shù)中所含代碼較多時(shí),通常只在類中進(jìn)行原型的說(shuō)明,在類外對(duì)函數(shù)進(jìn)行定義。,例: class Person char name12; int age; char sex4; public: void Print( ) coutname,age,sexendl; /省略其它成員 ;,在類中定義的成員函數(shù),在類外定義成員函數(shù)時(shí),函

7、數(shù)名應(yīng)該包含: 類名作用域分辯符(:)原函數(shù)名,指明該函數(shù)是哪個(gè)類的成員,class Person char name12; int age; char sex4; public: void Print ( ) ; /省略其它成員 ; void Person : Print( ) coutname,age,sexendl; ,例:,在類中聲明成員函數(shù)的原型,在類外定義成員函數(shù),類的成員函數(shù)可以重載,例: class Person char name12; int age; char sex4; public: void SetPerson(const char*,int,const char*

8、 =女); void SetPerson(int); /省略其它成員 ;,成員函數(shù)重載,缺省參數(shù),11.4.4 對(duì)象,對(duì)象的本質(zhì) 一個(gè)對(duì)象就是一個(gè)類的實(shí)例。一個(gè)對(duì)象就是一個(gè)具有某種類類型的變量。 對(duì)象的定義格式: 類名 對(duì)象名;,例: Person p1,p2;,公共代碼區(qū),SetPerson() GetName() GetSex() Print(),p1 p2,訪問對(duì)象的成員,對(duì)象名.數(shù)據(jù)成員名 對(duì)象名.成員函數(shù)名(參數(shù)表) 對(duì)象指針名-數(shù)據(jù)成員名 對(duì)象指針名-成員函數(shù)名(參數(shù)表),訪問對(duì)象的成員時(shí),要注意成員的訪問權(quán)限。,例: #include class Rectangle float

9、length,width; public: float Area( ) return length*width; float Perimeter( ) return 2*(length+width); ;,private:,以關(guān)鍵字class定義的類,成員的缺省訪問屬性為private。,void main( ) Rectangle r; r.width=45; r.length=54.2; coutthe area of rectangle is r.Area()endl; coutthe perimeter of rectangle is r.Perimeter()endl; ,非法訪問

10、私有成員!,#include class Rectangle float length,width; public: void SetWidth(float newWidth) width=newWidth; void SetLength(float newLength) length=newLength; float Area( ) return length*width; float Perimeter( ) return 2*(length+width); ;,例:,void main( ) Rectangle r; /定義對(duì)象 r.SetWidth(45); r.SetLength(5

11、4.2); coutThe area of rectangle is r.Area( )endl; coutThe perimeter of rectangle is r. Perimeter( )endl; ,11.4.5 對(duì)象數(shù)組,若一個(gè)數(shù)組中每個(gè)元素都是同類型的對(duì)象,則稱該數(shù)組為對(duì)象數(shù)組。 定義一維對(duì)象數(shù)組的格式為: ;,例11.5 對(duì)象數(shù)組的使用。 #include class Circle int radius; public: void setRadius(int r) radius=r; int getRadius( ) return radius; double area( )

12、 return 3.14*radius*radius; ; void main( ) Circle c3; c0.setRadius(6); c1.setRadius(2); c2.setRadius(15); for(int i=0;i3;i+) coutradius:ci.getRadius( ) ,area:ci.area( )endl; ,類Circle的定義,定義對(duì)象數(shù)組,11.4.6 this指針,一個(gè)成員函數(shù)被調(diào)用時(shí),系統(tǒng)自動(dòng)向它傳遞一個(gè)隱含的指針,該指針是調(diào)用該成員函數(shù)的對(duì)象的指針,在成員函數(shù)的函數(shù)體中可直接用this使用該指針。 在成員函數(shù)的實(shí)現(xiàn)中,當(dāng)訪問該對(duì)象的某成員時(shí),系

13、統(tǒng)自動(dòng)使用這個(gè)隱含的this指針。在定義成員函數(shù)的函數(shù)體時(shí),通常省略this指針。 例:Circle類的成員函數(shù) void setRadius(int r) radius=r; ,this-,this指針具有如下的缺省說(shuō)明: Circle *const this;,有時(shí)不得不顯式使用this指針。 數(shù)據(jù)成員名與函數(shù)成員的形參同名。例: class Name char* name; public: void SetName(char* name) if(name) this-name=new charstrlen(name)+1; strcpy(this-name,name); else thi

14、s-name=NULL; ;,引用對(duì)象本身。例: class Name char* name; public: void CopyName(Name,11.5 構(gòu)造函數(shù)和析構(gòu)函數(shù),構(gòu)造函數(shù)和析構(gòu)函數(shù):類的特殊成員。 構(gòu)造函數(shù): 創(chuàng)建對(duì)象,并初始化對(duì)象的數(shù)據(jù)成員。 析構(gòu)函數(shù): 撤銷對(duì)象,收回它所占內(nèi)存,及完成其它清理工作。,11.5.1 構(gòu)造函數(shù),構(gòu)造函數(shù)的定義格式 ClassName() /函數(shù)體,它與所在類同名。 它不得有返回值,甚至連關(guān)鍵字void也不許有。,例:,class Person char name12; int age; char sex4; public: Person(co

15、nst char*n,int a,const char*s) strcpy(name,n); age=a; strcpy(sex,s); /省略其它成員函數(shù) ;,例:,class Person char name12; int age; char sex4; public: Person(const char* n,int a,const char* s); /其它成員函數(shù)說(shuō)明 ; Person:Person(const char* n,int a,const char* s) strcpy(name,n); age=a; strcpy(sex,s); ,也可在類中聲明原型,在類外定義。,構(gòu)造

16、函數(shù)的特殊性:,構(gòu)造函數(shù)在定義類對(duì)象時(shí)由系統(tǒng)自動(dòng)調(diào)用。例:,void main( ) Person p(“張三”,20, “男” ); ,當(dāng)遇此定義語(yǔ)句時(shí),系統(tǒng)就調(diào)用構(gòu)造函數(shù): Person(const char* n,int a,const char* s) 創(chuàng)建對(duì)象p,并用實(shí)參初始化它的數(shù)據(jù)成員。,構(gòu)造函數(shù)可以重載。例:,class Point float x,y; public: Point( )x=0;y=0; /(1) Point(float a,float b)x=a;y=b; /(2) / ; void main( ) Point p1; /匹配(1) Point p2(2.0,

17、4.2); /匹配(2) ,構(gòu)造函數(shù)中初始化數(shù)據(jù)成員的方法,在函數(shù)體中用賦值等語(yǔ)句進(jìn)行 使用成員初始化列表,初始化列表,格式: 在形參表和函數(shù)體之間,以:號(hào)開頭,由多個(gè)以逗號(hào)分隔的初始化項(xiàng)構(gòu)成。即 :數(shù)據(jù)成員名1(初值1),數(shù)據(jù)成員名n(初值n) 舉例: Person:Person( ):name(zhang),age(22) strcpy(sex,男); 執(zhí)行順序:帶有初始化表的構(gòu)造函數(shù)執(zhí)行時(shí),首先執(zhí)行初始化表,然后再執(zhí)行函數(shù)體。,數(shù)據(jù)成員的初始化,普通數(shù)據(jù)成員的初始化既可在函數(shù)體進(jìn)行,也可在初始化表進(jìn)行。例:,(方法1) Point:Point(int x1,int y1) x=x1; y

18、=y1; 或(方法2) Point:Point(int x1,int y1):x(x1),y(y1) ,const數(shù)據(jù)成員、const對(duì)象成員和從基類繼承的數(shù)據(jù)成員的初始化必須用初始化表。,缺省的構(gòu)造函數(shù),C+規(guī)定,每個(gè)類至少有一個(gè)構(gòu)造函數(shù),否則就不能創(chuàng)建該類的對(duì)象。例:,class Rectangle float length,width; public: float Area( ); float Perimeter( ); ; /類的實(shí)現(xiàn) void main( ) Rectangle rect; ,能否創(chuàng)建Rectangle類的對(duì)象?,類中若未定義構(gòu)造函數(shù),則C+編譯系統(tǒng)自動(dòng)提供一個(gè)缺省的

19、構(gòu)造函數(shù)。缺省的構(gòu)造函數(shù)無(wú)參,函數(shù)體為空,僅創(chuàng)建對(duì)象,不作任何初始化工作。,class Rectangle float length,width; public: float Area( ) ; float Perimeter( ); ; /類的實(shí)現(xiàn) void main( ) Rectangle rect; ,因系統(tǒng)提供了默認(rèn)的構(gòu)造函數(shù): Rectangle( ) ,只要類中定義了一個(gè)構(gòu)造函數(shù),C+編譯器就不再提供缺省的構(gòu)造函數(shù),如還想要無(wú)參構(gòu)造函數(shù),則必須自己定義。例: class Circle int radius; public: Circle(int r) radius=r; /(1)

20、 ; Circle c1; Circle c2(5);,因該類有帶一個(gè)參數(shù)的構(gòu)造函數(shù),故系統(tǒng)不再提供無(wú)參的缺省構(gòu)造函數(shù)!,匹配(1),沒有無(wú)參構(gòu)造函數(shù),對(duì)上例的修改方法1: class Circle int radius; public: Circle(int r) radius=r; /(1) Circle( ) /(2) ; Circle c1(3); Circle c2;,匹配(1),匹配(2),添加無(wú)參構(gòu)造函數(shù)!,對(duì)上例的修改方法2 : class Circle int radius; public: Circle(int r=0) radius=r; /(1) ; Circle c1

21、(3); Circle c2;,匹配(1),匹配(1),參數(shù)帶默認(rèn)值的構(gòu)造函數(shù)! 所有參數(shù)都帶默認(rèn)值的構(gòu)造函數(shù)也是缺省的構(gòu)造函數(shù)。,使用參數(shù)帶缺省值的構(gòu)造函數(shù)時(shí),應(yīng)防二義性。如: class Circle int radius; public: Circle() /L1 Circle(int r=0) radius=r; /L2 ; Circle c1; /L3 錯(cuò)誤!產(chǎn)生二義性 Circle c2(5); /匹配L2行的構(gòu)造函數(shù) 當(dāng)編譯L3行的語(yǔ)句時(shí),出錯(cuò)。因Circle類定義了兩個(gè)缺省的構(gòu)造函數(shù),編譯器不知道是調(diào)用L1行定義的Circle( )還是調(diào)用L2行定義的Circle(int r=

22、0)。,11.5.2 析構(gòu)函數(shù),作用: 與構(gòu)造函數(shù)相反,在對(duì)象被撤消時(shí)由系統(tǒng)自動(dòng)調(diào)用,做清理工作。 特點(diǎn): 析構(gòu)函數(shù)名必須與類名相同,并在其前面加上字符“”,以便和構(gòu)造函數(shù)名相區(qū)別。 析構(gòu)函數(shù)沒有返回值,函數(shù)名前也不能用關(guān)鍵字void。 析構(gòu)函數(shù)沒有參數(shù),換言之,析構(gòu)函數(shù)是唯一的,析構(gòu)函數(shù)無(wú)法重載。,例11.9 調(diào)用析構(gòu)函數(shù)。 #include class Point int x,y; public: Point() x=y=0;coutDefault constructor called.n; Point(int a,int b) x=a;y=b; coutConstructor with

23、parameters called.n; Point( ) coutDestructor called.x,yn; void print( ) coutx,yn; ;,為了觀察調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的過(guò)程,分別在構(gòu)造函數(shù)和析構(gòu)函數(shù)內(nèi)添加了輸出調(diào)用信息的語(yǔ)句。,void main( ) Point p1(5,8),p2; p1.print( ); p2.print( ); Point p2(3,2); p2.print(); coutExit main!n; ,程序運(yùn)行結(jié)果: Constructor with parameters called. Default constructor call

24、ed. 5,8 0,0 Constructor with parameters called. 3,2 Destructor called.3,2 Exit main! Destructor called.0,0 Destructor called.5,8,從該程序的輸出結(jié)果看: 當(dāng)創(chuàng)建對(duì)象時(shí),系統(tǒng)自動(dòng)調(diào)用相匹配的構(gòu)造函數(shù); 當(dāng)撤銷對(duì)象時(shí),系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)。 對(duì)象撤銷的順序與創(chuàng)建的順序正好相反。 在相同的生存期的情況下,先創(chuàng)建的對(duì)象后撤銷,后創(chuàng)建的對(duì)象先撤銷。,若類的定義中沒有顯式定義析構(gòu)函數(shù),則編譯器自動(dòng)為該類產(chǎn)生一個(gè)缺省的析構(gòu)函數(shù)。其格式為: ClassName:ClassName(

25、) 它不執(zhí)行任何操作。 無(wú)需顯式定義析構(gòu)函數(shù)的典型情況: 撤消對(duì)象時(shí)不做任何清理工作。 需要顯式定義析構(gòu)函數(shù)的典型情況: 類中包含指向動(dòng)態(tài)內(nèi)存的指針數(shù)據(jù)成員。由于它們所指向的動(dòng)態(tài)內(nèi)存空間是對(duì)象自己管理的,因此在對(duì)象即將撤消時(shí),需通過(guò)析構(gòu)函數(shù)將所管理的動(dòng)態(tài)內(nèi)存空間及時(shí)釋放。,例11.10 使用析構(gòu)函數(shù),收回動(dòng)態(tài)分配的存儲(chǔ)空間。 #include #include class Person char* name; int age; public: Person(char* n,int a) if(n) name=new charstrlen(n)+1; strcpy(name,n); else n

26、ame=0; age=a; Person( ) delete name; void Print() coutname,ageendl; ; void main( ) Person p(“John”,20); p.Print( ); ,申請(qǐng)動(dòng)態(tài)內(nèi)存,釋放動(dòng)態(tài)內(nèi)存,對(duì)象釋放順序: 對(duì)象釋放的順序與創(chuàng)建的順序正好相反。在相同的生存期的情況下,先創(chuàng)建的對(duì)象后釋放,后創(chuàng)建的對(duì)象先釋放。,11.5.3 構(gòu)造函數(shù)的類型轉(zhuǎn)換功能,如果類定義中提供了只帶一個(gè)參數(shù)(沒有其它參數(shù),或其它參數(shù)都有缺省值)的構(gòu)造函數(shù),則當(dāng)一個(gè)其它類型的數(shù)值或變量x賦值給該類的對(duì)象A時(shí),由于類型不一致,系統(tǒng)自動(dòng)以x為實(shí)參調(diào)用該類的單參數(shù)

27、構(gòu)造函數(shù),創(chuàng)建一個(gè)該類的臨時(shí)對(duì)象,并將該臨時(shí)對(duì)象賦值給A,從而實(shí)現(xiàn)了隱式類型轉(zhuǎn)換。,例11.11 構(gòu)造函數(shù)完成類型轉(zhuǎn)換功能的例子。 #include class Money int yuan,jiao,fen; public: Money (double d) int t=d*100; yuan=t/100;jiao=(t-yuan*100)/10;fen=t%10; Money (int y=0,int j=0,int f=0) yuan=y;jiao=j;fen=f; void print( ) coutyuan“元”jiao“角”fen“分n; ;,單參數(shù) 構(gòu)造函數(shù),void main(

28、 ) Money m1(25,5,7),m2(2.65); m1.print( ); m2.print( ); Money m3=4.57; m3.print( ); m3= 3.29 ; m3.print( ); ,隱式類型轉(zhuǎn)換:調(diào)用單參數(shù)構(gòu)造函數(shù),創(chuàng)建Money類型的臨時(shí)對(duì)象。,并不做隱式類型轉(zhuǎn)換,等價(jià)于: Money m3(4.57);,11.5.4 拷貝構(gòu)造函數(shù),拷貝構(gòu)造函數(shù):特殊的構(gòu)造函數(shù),其形參是本類的對(duì)象的引用,其作用是使用一個(gè)已經(jīng)存在的對(duì)象(由拷貝構(gòu)造函數(shù)的參數(shù)指定的對(duì)象)去初始化一個(gè)新的同類的對(duì)象。 定義一個(gè)拷貝構(gòu)造函數(shù)的一般形式為: ClassName:ClassName(

29、ClassName public: Point(int a=0,int b=0) x=a;y=b; Point(Point,double Distance(Point p1,Point p2) int dx=p1.GetX()-p2.GetX(); int dy=p1.GetY()-p2.GetY(); return sqrt(dx*dx+dy*dy); Point Mid(Point ,函數(shù)Distance(Point,Point)的形參為類的對(duì)象,當(dāng)執(zhí)行函數(shù)調(diào)用distance(p0,p3)時(shí),實(shí)參初始化形參,兩次調(diào)用拷貝構(gòu)造函數(shù),分別用實(shí)參對(duì)象p0和p3初始化形參對(duì)象p1和p2。 若函數(shù)

30、形參是對(duì)象的引用,則調(diào)用該函數(shù)時(shí),不調(diào)用拷貝構(gòu)造函數(shù),如本例的Mid函數(shù)所示。,結(jié)果(VC6 with sp6): 調(diào)用了拷貝構(gòu)造函數(shù)! 調(diào)用了拷貝構(gòu)造函數(shù)! x=8,y=15 x=8,y=15 x=8,y=15 調(diào)用了拷貝構(gòu)造函數(shù)! 調(diào)用了拷貝構(gòu)造函數(shù)! 8.06226,默認(rèn)拷貝構(gòu)造函數(shù): 若定義類時(shí)未顯式定義該類的拷貝構(gòu)造函數(shù),則編譯系統(tǒng)會(huì)在編譯該類時(shí)自動(dòng)生成一個(gè)默認(rèn)拷貝構(gòu)造函數(shù)。 默認(rèn)拷貝構(gòu)造函數(shù)的功能是把一個(gè)已經(jīng)存在的對(duì)象的每個(gè)數(shù)據(jù)成員的值逐個(gè)復(fù)制到新建立對(duì)象對(duì)應(yīng)的數(shù)據(jù)成員中。 例11.12中類Point的拷貝構(gòu)造函數(shù)與默認(rèn)的拷貝構(gòu)造函數(shù)功能一樣,不必顯式定義。 何時(shí)顯式定義拷貝構(gòu)造函

31、數(shù)?若類中包含指向動(dòng)態(tài)內(nèi)存的指針時(shí),用默認(rèn)的拷貝構(gòu)造函數(shù)初始化對(duì)象,將帶來(lái)嚴(yán)重問題,如例11.13所示。,例11.13 默認(rèn)拷貝的構(gòu)造函數(shù)。 #include #include class String char *p; public: String(char*c=0) if(c) p=new charstrlen(c)+1; strcpy(p,c); else p=NULL; String( ) delete p; void Show( ) coutstring=pn; ;,void main( ) String s1(student); String s2(s1);/A s1.Show(

32、); s2.Show( ); ,s1.p,s1,堆內(nèi)存,s2.p,s2,執(zhí)行A行語(yǔ)句:調(diào)用默認(rèn)拷貝構(gòu)造函數(shù),用s1對(duì)象初始化s2對(duì)象,使s2對(duì)象的成員指針p與s1對(duì)象的成員指針p指向同一片內(nèi)存。 主函數(shù)結(jié)束:先撤消s2,s2對(duì)象釋放其所指動(dòng)態(tài)內(nèi)存;其后撤銷s1對(duì)象,但因s1對(duì)象所指動(dòng)態(tài)內(nèi)存已被s2對(duì)象釋放,造成重復(fù)釋放同一塊動(dòng)態(tài)內(nèi)存,出現(xiàn)運(yùn)行錯(cuò)誤。 定義拷貝構(gòu)造函數(shù),避免上述錯(cuò)誤: String(String ,s,t,u,d,e,n,0,t,11.5.5 對(duì)象成員與構(gòu)造函數(shù),對(duì)象成員:一個(gè)類的對(duì)象可做另一個(gè)類的數(shù)據(jù)成員。 例如: class Date int year,month,day;

33、public: Date(int y,int m,int d) year=y;month=m;day=d; ; class Person char name12; char sex4; Date birthday; /對(duì)象成員 public: Person(char*, char*,int,int,int); ;,對(duì)象成員的初始化 通過(guò)初始化表進(jìn)行,如: Person:Person(char*n,char*s,int y,int m,int d) :birthday(y,m,d) strcpy(name,n); strcpy(sex,s); 若未在初始化表中初始化對(duì)象成員,則系統(tǒng)自動(dòng)調(diào)用該對(duì)象

34、成員的缺省的構(gòu)造函數(shù)來(lái)初始化。 若類中包含對(duì)象成員,則在創(chuàng)建該類的對(duì)象時(shí),先調(diào)用對(duì)象成員的構(gòu)造函數(shù),初始化相應(yīng)的對(duì)象成員,后執(zhí)行該類的構(gòu)造函數(shù),初始化該類的其他成員。 如果一個(gè)類包含多個(gè)對(duì)象成員,對(duì)象成員的構(gòu)造函數(shù)的調(diào)用順序由它們?cè)谠擃愔械恼f(shuō)明順序決定,而與它們?cè)诔跏蓟碇械捻樞驘o(wú)關(guān)。,例11.14 初始化對(duì)象成員。 #include class Point int x,y; public: Point(int a,int b) x=a; y=b; coutConstructor of class Point is called.n; void Show( ) coutx=x,y=yendl;

35、 ;,class Rectangle Point p; int length,width; public: Rectangle(int l,int w,int a,int b):p(a,b) length=l; width=w; coutConstructor of class Rectangle is called.n; void Show( ) p.Show( ); coutlength=length,width=widthendl; ; void main( ) Rectangle r(5,4,45,55); r.Show( ); ,程序運(yùn)行結(jié)果: Constructor of clas

36、s Point is called. Constructor of class Rectangle is called. x=45,y=55 length=5,width=4,11.6 友元,有時(shí)需要在對(duì)象外部頻繁訪問對(duì)象私有的或保護(hù)的數(shù)據(jù)成員,若通過(guò)調(diào)用公有成員函數(shù)間接訪問,由于參數(shù)傳遞、類型檢查等都需占用時(shí)間,必然降低程序的運(yùn)行效率。 使用友元可在對(duì)象外部直接訪問對(duì)象私有的和保護(hù)的數(shù)據(jù)成員。 友元以類的封裝性的有限破壞為代價(jià)來(lái)提高程序的運(yùn)行效率,應(yīng)謹(jǐn)慎使用。 友元分為:友元函數(shù)和友元類。,11.6.1 友元函數(shù),友元函數(shù)的說(shuō)明格式: friend FuncName(); 例11.15 用友

37、元函數(shù)的方法計(jì)算兩點(diǎn)距離。 #include #include class Point int x,y; public: Point(int i=0,int j=0) x=i;y=j; int GetX( ) return x; int GetY( ) return y; friend double distance(Point,普通函數(shù)distance( )聲明為Point類的友元函數(shù)。,double distance(Point ,程序運(yùn)行結(jié)果: The distance is:9.43398,友元函數(shù)distance( )可通過(guò)對(duì)象名直接訪問Point類的對(duì)象p1和p2的私有數(shù)據(jù)成員x和

38、y,提高了程序的效率。,友元函數(shù)說(shuō)明: 友元函數(shù)應(yīng)在類中說(shuō)明,可放在類的私有、公有或保護(hù)部分,效果一樣。友元函數(shù)體可在類內(nèi)或類外定義。 友元函數(shù)不是類的成員,不帶this指針,因此必須將對(duì)象名或?qū)ο蟮囊米鳛橛言瘮?shù)的參數(shù),并在函數(shù)體中用運(yùn)算符“.”來(lái)訪問對(duì)象的成員。如上例中的p1.x。 友元函數(shù)可直接訪問相關(guān)類中的所有成員。 一個(gè)類的成員函數(shù)也可作為另一個(gè)類的友元函數(shù),例如: class A int f(); ; class B /成員定義 friend int A:f();/聲明類A的成員函數(shù)f( ) ; / 是類B的友元,在聲明這個(gè)友元函數(shù)時(shí)需要在函數(shù)名前面加上它的類名和作用域運(yùn)算符“:

39、”。,11.6.2 友元類,若聲明A類為B類的友元,則A類的所有成員函數(shù)都成為B類的友元函數(shù)。有時(shí)友元類的使用也是必要的選擇。 例11.16 友元類。 #include #include class Date int year,month,day; public: Date(int y=0,int m=0,int d=0) year=y;month=m;day=d; void display() coutyearmonthday; friend class Person; ;,class Person char name12; char sex4; Date birthday; public:

40、 Person(char*n,int y,int m,int d,char*s) strcpy(name,n); strcpy(sex,s); birthday.year=y; birthday.month=m; birthday.day=d; void display( ) coutname:name,sex:sex; cout,birthday:birthday.year. birthday.month.birthday.dayendl; ; void main( ) Person p(“張三”,1983,8,20,”男”); p.display( ); ,程序運(yùn)行結(jié)果: name:張三,

41、sex:男,birthday:1983.8.20,因Person類為Date類的友元,在Person類的成員函數(shù)可直接操作Date類的對(duì)象birthday的數(shù)據(jù)成員。,友元的其它注意事項(xiàng): 友元關(guān)系沒有傳遞性。例如,說(shuō)明類A是類B的友元,類B是類C的友元時(shí),類A并不一定是類C的友元。 友元關(guān)系不具有交換性,即說(shuō)明類A為類B的友元時(shí),類B并不一定是類A的友元。 友元關(guān)系沒有繼承性。因友元函數(shù)不是類的成員函數(shù),當(dāng)然不存在繼承關(guān)系。 謹(jǐn)慎使用友元。友元提高程序的運(yùn)行效率是通過(guò)破壞類的封裝性取得的,若過(guò)多過(guò)濫使用友元,則會(huì)嚴(yán)重降低程序的可維護(hù)性。,11.7 類的靜態(tài)成員,分類:,靜態(tài)數(shù)據(jù)成員,靜態(tài)成員

42、函數(shù),11.7.1 靜態(tài)數(shù)據(jù)成員,靜態(tài)數(shù)據(jù)成員的必要性,/學(xué)生類 class Student int No; char *name; ,若要統(tǒng)計(jì)學(xué)生總數(shù),這個(gè)數(shù)據(jù)存放在什么地方呢?,類外變量?,不能實(shí)現(xiàn)數(shù)據(jù)的隱藏!,類中增加數(shù)據(jù)成員?,冗余!不一致!,靜態(tài)數(shù)據(jù)成員的定義:先在類體內(nèi),做引用性說(shuō)明,即在該成員名的類型說(shuō)明符前加關(guān)鍵字static。后在文件作用域做定義性說(shuō)明。,例: class Student int No; char *name; static int count;/引用性說(shuō)明:說(shuō)明靜態(tài) /數(shù)據(jù)成員count的訪問權(quán)限和作用域 ; int Student:count=0;/定義性

43、說(shuō)明:為靜態(tài) /數(shù)據(jù)成員count分配內(nèi)存和初始化,與普通數(shù)據(jù)成員的區(qū)別:類的普通數(shù)據(jù)成員在類的每個(gè)對(duì)象中都擁有一個(gè)拷貝;而靜態(tài)數(shù)據(jù)成員,每個(gè)類只有一個(gè)拷貝,由該類的所有對(duì)象共同維護(hù)和使用,從而實(shí)現(xiàn)了同一類的不同對(duì)象之間的數(shù)據(jù)共享。,例:void main( ) Student s1,s2; ,count,靜態(tài)存儲(chǔ)區(qū),s1與s2共有,靜態(tài)數(shù)據(jù)成員的引用: 類名:靜態(tài)數(shù)據(jù)成員名 或 對(duì)象名.靜態(tài)數(shù)據(jù)成員名 或 對(duì)象指針-靜態(tài)數(shù)據(jù)成員名 訪問靜態(tài)數(shù)據(jù)成員時(shí)也要注意訪問權(quán)限。,例11.17 具有靜態(tài)數(shù)據(jù)成員的Apple類。,#include class Apple float weight; sta

44、tic int count;/靜態(tài)數(shù)據(jù)成員的引用性說(shuō)明 static float total_weight; public: Apple(float=0); Apple( ); void Show( ); ;,Apple:Apple(float w) weight=w; count+; total_weight+=weight; coutNumber of apples=countn; Apple: Apple( ) count-; total_weight-=weight; coutNumber of apples=countn; void Apple: Show( ) coutweight

45、=weight ,total_weight=total_weightn; ,/靜態(tài)數(shù)據(jù)成員的定義性說(shuō)明:默認(rèn)值為0 int Apple:count; float Apple:total_weight; void main( ) Apple redone(100); Apple greenone(200); Apple yellowone(250); redone.Show( ); greenone.Show( ); yellowone.Show( ); ,11.7.2 靜態(tài)成員函數(shù),采用靜態(tài)函數(shù)成員的好處是可以不依賴于任何對(duì)象,直接訪問靜態(tài)數(shù)據(jù)成員。 靜態(tài)成員函數(shù)的定義格式: static 返

46、回值類型 成員函數(shù)名(參數(shù)表); 靜態(tài)成員函數(shù)的引用格式: :() 或 .(),例11.18 具有靜態(tài)數(shù)據(jù)成員和靜態(tài)成員函數(shù)的Apple類。,#include class Apple float weight; static int count; static float total_weight; public: Apple(float=0); Apple(); void ShowWeight(); static void ShowCount(); static void ShowTotalWeight(); ;,Apple:Apple(float w) weight=w;count+; t

47、otal_weight+=weight; coutNumber of apples=countn; Apple:Apple( ) count-; total_weight-=weight; coutNumber of apples=countn; void Apple: ShowWeight( ) coutweight=weightn; void Apple:ShowCount( ) coutNumber of apples=countn; void Apple:ShowTotalWeight( ) coutTotal weight of apples= total_weightn; ,int

48、 Apple:count; float Apple:total_weight; void main( ) Apple:ShowCount( ); Apple:ShowTotalWeight( ); Apple redone(100),greenone(200),yellowone(250); redone.ShowWeight( ); greenone.ShowWeight( ); yellowone.ShowWeight( ); Apple:ShowCount( ); Apple:ShowTotalWeight( ); ,程序運(yùn)行結(jié)果: Number of apples=0 Total we

49、ight of apples=0 weight=100 weight=200 weight=250 Number of apples=3 Total weight of apples=550,靜態(tài)成員函數(shù)可直接訪問靜態(tài)數(shù)據(jù)成員,但不能直接訪問非靜態(tài)數(shù)據(jù)成員(因其沒有this指針)。若要訪問非靜態(tài)數(shù)據(jù)成員,則可通過(guò)形參對(duì)象來(lái)訪問。如: class Myclass int x; static int y; public: static int f(Myclass m); ; int Myclass:y=9; int Myclass:f(Myclass m) coutx+y; /對(duì)x的訪問是錯(cuò)誤的

50、return m.x+y; /正確 ,11.8 const對(duì)象和成員函數(shù),常成員函數(shù):在參數(shù)表后用const修飾。 定義格式: () const; 特點(diǎn):常成員函數(shù)不能直接改變本對(duì)象的數(shù)據(jù)成員,也不能調(diào)用該對(duì)象的非const成員函數(shù)間接改變本對(duì)象的數(shù)據(jù)成員,否則編譯時(shí)會(huì)產(chǎn)生出錯(cuò)信息。 用途:主要用于定義不改變數(shù)據(jù)成員的成員函數(shù)。 const對(duì)象:用const說(shuō)明的對(duì)象。 定義格式: const (); 特點(diǎn):其數(shù)據(jù)成員在該對(duì)象的生存期間不能改變。 例如: const Date birthday(1983,7,13); const對(duì)象只能調(diào)用常成員函數(shù)(構(gòu)造函數(shù)和析構(gòu)函數(shù)除外),以保證其數(shù)據(jù)成員

51、不被修改。,例11.19 常成員函數(shù)舉例。,#include class Date int year,month,day; public: Date(int y,int m,int d) year=y;month=m;day=d; void SetDate(int y,int m,int d) year=y;month=m;day=d; void display( ) coutyear,month,dayendl; void display( ) const coutyear,month,dayendl; ;,void main( ) Date weekend(2005,7,8); weeke

52、nd.display( ); weekend.SetDate(2005,7,22); weekend.display( ); const Date birthday(1983,7,13); birthday.display( ); ,程序運(yùn)行結(jié)果: 2005,7,8 2005,7,22 1983,7,13,常對(duì)象和常成員函數(shù)的說(shuō)明: 常成員函數(shù)在類外定義時(shí)也應(yīng)帶const關(guān)鍵字。例如: void Date:display( ) const coutyear,month,dayendl; 常成員函數(shù)不能直接改變本對(duì)象的數(shù)據(jù)成員,也不能調(diào)用該對(duì)象的非const成員函數(shù)間接改變本對(duì)象的數(shù)據(jù)成員。若常

53、成員函數(shù)改變數(shù)據(jù)成員的值,則編譯時(shí)將出現(xiàn)出錯(cuò)信息。 const可用于區(qū)分函數(shù)的重載。如類Date中有聲明: void display( ); void display( ) const; 常對(duì)象只能調(diào)用其常成員函數(shù),不能調(diào)用其它成員函數(shù)。若常對(duì)象調(diào)用非const成員函數(shù),如: birthday.SetDate(2005,7,22); 則編譯時(shí)將出現(xiàn)出錯(cuò)信息。,11.9 應(yīng)用實(shí)例,例11.20 用類和對(duì)象編程解決實(shí)際問題。設(shè)有若干學(xué)生數(shù)據(jù),包括學(xué)號(hào)、姓名、數(shù)學(xué)成績(jī)和C+成績(jī),求每位學(xué)生的總分及每門課程的平均分。 分析: Student類包括學(xué)號(hào)、姓名等數(shù)據(jù)成員,以及對(duì)這些數(shù)據(jù)進(jìn)行操作的函數(shù)成員。

54、其中,靜態(tài)數(shù)據(jù)成員count、msum和csum,分別存放學(xué)生人數(shù)、數(shù)學(xué)和C+課程的總分。 鏈表類StuList用于存放學(xué)生數(shù)據(jù),可完成鏈表創(chuàng)建、輸出等任務(wù)。它聲明為類Student的友元,更便于高效操作Student類的數(shù)據(jù)成員。,#include #include class Student /學(xué)生類 protected: int no; /學(xué)號(hào) char name10; /姓名 float math,cpp; /數(shù)學(xué)成績(jī)、C+成績(jī) static int count; /累計(jì)總?cè)藬?shù) static float msum,csum;/分別累計(jì)數(shù)學(xué)和C+總分 Student* next; pub

55、lic: Student( ) Student(int,char*,float,float,Student* =NULL); float sum( ) const /計(jì)算每位學(xué)生的總分 return math+cpp; ,void show1( ) const /輸出每位學(xué)生的基本信息 coutmath=math; this-cpp=cpp; this-next=next; count+; msum+=math; csum+=cpp; ,class StuList Student*head; public: StuList( ) head=NULL; StuList( ); void crea

56、te( ); /創(chuàng)建鏈表 void print( ) const; /輸出鏈表 ; StuList:StuList( ) Student*p; while(head) p=head; head=head-next; delete p; ,void StuList:create( ) /尾結(jié)點(diǎn)插入法創(chuàng)建單向鏈表 Student*p1,*p2; int no; char name10; float math,cpp; coutno; while(no!=-1) coutnamemathcpp; p1=new Student(no,name,math,cpp); if(!head) head=p1,

57、p2=p1;else p2-next=p1,p2=p1; coutno; ,void StuList:print( ) const Student* p=head; coutshow1( ); p=p-next; cout每門平均分:t; Student:show2( ); int Student:count; /定義靜態(tài)數(shù)據(jù)成員并初始化 float Student:msum,Student:csum; void main( ) StuList li; li.create( ); li.print( ); ,程序的一次運(yùn)行結(jié)果如下: 輸入學(xué)號(hào),-1表示結(jié)束:1 輸入姓名及數(shù)學(xué)、C+語(yǔ)言成績(jī):Tom 90 95 輸入學(xué)號(hào),-1表示結(jié)束:2 輸入姓名及數(shù)學(xué)、C+語(yǔ)言成績(jī):Sun 9

溫馨提示

  • 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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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)論