c++類和對象的進一步描述.ppt_第1頁
c++類和對象的進一步描述.ppt_第2頁
c++類和對象的進一步描述.ppt_第3頁
c++類和對象的進一步描述.ppt_第4頁
c++類和對象的進一步描述.ppt_第5頁
已閱讀5頁,還剩60頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、1,20111431,20111421,2,3.4 對象數組,數組不僅可以由簡單變量組成, 也可以由對象組成。 例如 Box boxArr50; /假設已聲明了Box類,定義boxArr數組,有50個元素 如果構造函數有多個參數,則在定義數組時,應在花括號中分別寫出構造函數并指定實參。 例:構造函數 Box:Box(int h=10,int w=12,int l=15) height=h;width=w;length=l; Box b3=0,2,16 /不提倡 Box b3=Box(0), Box(2), Box(16,25) /提倡 Box b3=Box(0,0,0), Box(2,3,4)

2、, Box(16,3,56) ; /提倡,例3.6,3,3.5 對象指針 指針可以指向一般的變量,也可以指向對象。,3.5.1 指向對象的指針 對象的指針:建立對象時,系統(tǒng)會為每個對象分配一定的存儲空間,以存放其成員。對象空間的起始地址就是對象的指針。 指向對象的指針: 類名 *對象指針名; 指向對象指針的使用: (*p).類成員 /格式1 p-類成員 /格式2,4,1.指向對象數據成員的指針 對象中的數據成員也有地址,存放對象成員地址的指針變量就是指向對象成員的指針變量。 假設時間類Time的成員變量hour為公用的 int *p; p=,3.5.2 指向對象成員的指針,5,2.指向對象成員

3、函數的指針,int max(int x,int y) return xy?x:y; int main() int (*f)(int,int); f= ,復習:指向函數的指針,6,指向對象成員函數的指針: 普通函數指針: 例:void (*p)();/如果寫成void *p(),表示函數p的函數值類型為void *型 成員函數指針: 例:void (Time:*p)(); 成員函數指針賦值 (在VC+系統(tǒng)中,可以不寫 把count聲明為可變的數據成員,這樣可以用聲明為const的成員函數來修改它的值。,11,#include using namespace std; class Time pub

4、lic: Time(int,int,int); int hour; int minute; int sec; void get_time(); void set_time(); ; int main() const Time t1(10,13,56); t1.set_time(); t1.get_time(); return 0; ,Time:Time(int h,int m,int s):hour(h),minute(m),sec(s) void Time:get_time() couthour:minute:secendl; void Time:set_time() hour=22; ,1

5、2,編譯出錯,cannot convert this pointer from const class Time to class Time class Time public: Time(int,int,int); int hour; int minute; int sec; void get_time() const ; void set_time() const ; ; int main() const Time t1(10,13,56); t1.set_time(); t1.get_time(); return 0; ,Time:Time(int h,int m,int s):hour

6、(h),minute(m),sec(s) void Time:get_time() const couthour:minute:secendl; void Time:set_time() const hour=22; ,14,編譯出錯,error C2166: l-value specifies const object 注:常成員函數可以訪問對象的數據成員,但不可修改常對象中的數據成員。,15,#include using namespace std; class Time public: Time(int,int,int); mutable int hour; int minute; in

7、t sec; void get_time() const; void set_time() const; ; int main() const Time t1(10,13,56); t1.set_time(); t1.get_time(); return 0; ,Time:Time(int h,int m,int s):hour(h),minute(m),sec(s) void Time:get_time()const couthour:minute:secendl; void Time:set_time() const hour=22; ,16,課堂練習,課后習題6、7,17,3.6.2 常

8、對象成員,可以在聲明類時將成員聲明為const,即聲明常數據成員和常成員函數。,18,3.6.2 常對象成員 1.常數據成員 定義:用const聲明的數據成員,則該成員的值不能被改變。 格式: 常數據成員只能通過構造函數的參數初始化表對常數據成員進行初始化。,Time:Time(int h)hour=h;/非法。 /因為常成員是不能被賦值 Time:Time(int h):hour(h) /合法 因為常數據成員是不能被賦值的。,const 數據類型 變量名;,19,2.常成員函數 格式: 常成員函數只能引用本類中的數據成員,而不能修改它們。,函數返回類型 函數名(參數表) const ;,20

9、,3.6.3 指向對象的常指針,引入:防止修改指針的值。 實現辦法:常指針。,21,3.6.3 指向對象的常指針 格式: 說明:指針值保持初值不能改變,即指針為常變量。 舉例: 用途:,int i=10,j=11; int * const p= /error C2166: l-value specifies const object,類名 * const 指針名;,用常指針作為形參,目的是不允許在函數執(zhí)行過程中改變指針變量的值,使其始終指向原來的對象。這樣比用人工來保證形參不被修改更可靠。,22,3.6.4 指向常對象的指針變量 引入:指向常變量的指針變量 格式: 對常變量,只能用指向常變量的

10、指針變量指向它。 const int pi=3.14; const int * pt= / ok: 非const變量值不能符給const類型的變量,const 類型名 *指針變量名;,23,指向常對象的指針變量,則其指向的對象是不能通過指針來改變的。 const double *cptr; / cptr may point to a double that is const *cptr = 42; / error:不能給*cptr重新復值 指向常變量的指針變量,也可以指向未被聲明為const的變量,但是不能通過此指針變量改變該變量的值。,const int i=10; int j=11; co

11、nst int *p= /error:p指向常整數,則*p為常量,不可對常量賦值,本質上來說,由于沒有方法分辨cptr所指的對象是否為const,系統(tǒng)會把它所指向的所有都視為const,24,“指向常對象的指針”的應用 在實際程序中,指向const的指針常用作函數的形參。將形參定義為指向const的指針,以確保傳遞給函數的實際對象在函數中不因為形參而被修改。 例如: void show_array(const double ar,int n) const意味著show_array()不能修改傳遞給它的數組中的值。,25,表3.2 用指針變量作形參時形參和實參的對應關系,26,指向對象的常指針與

12、指向常對象的指針的區(qū)別 Time * const p; 指向對象的常指針變量,必須在聲明時初始化。p本身的值為常量,不可變。p被綁定到所指向變量。 const Time *p; 指向常對象的指針變量。p指向常對象,p本身的值可變,但不可通過p修改p所指向的變量。p具有“只讀”權限,27,3.6.5 對象的常引用 解讀 例3.8。 如果不希望在函數中修改實參t1的值,可以把引用t聲明為const,函數原型為 void fun(const Time delete p; 第二章作業(yè)“附加2.3”,可使用此法創(chuàng)建動態(tài)數組,并在析構函數中釋放動態(tài)數組。,29,3.8.1、對象的賦值,3.8、對象的賦值和

13、復制,對象之間的賦值也是通過賦值運算符“=”進行的,這是通過對賦值運算符的重載實現的(關于運算符的重載將在第4章中介紹)。實際上這個過程是通過成員復制來完成的,即將一個對象的成員值一一復制給另一對象的對應成員,30,作用:用一個已經存在的對象(由拷貝構造函數的參數指定),去初始化同類的一個新對象??截惖玫降膶ο笈c原對象具有完全相同的數據成員,即完全相同的屬性。 拷貝構造函數是一種特殊的構造函數,具有構造函數的所有特征。,3.8.2 對象的復制,31,拷貝構造函數的聲明,Class 類名 public : 類名(形參表);/構造函數 類名(類名 Y=yy; Point(Point ,33,拷貝構

14、造函數的調用,普通構造函數:在對象創(chuàng)建時調用。 拷貝構造函數: 當用類的一個對象去初始化該類的另一個對象。 如果函數的形參是類的對象,函數調用,進行形參與實參的結合時。 如果函數的返回值是類的對象,函數執(zhí)行完成返回調用者時。,34,用一個對象去初始化該類的另一個對象,int main() Point A(1,2); Point B(A); coutB.GetX()endl; return 0; ,35,函數的形參是類的對象,函數調用,形參與實參結合時。,void f(Point p) coutp.GetX()endl; int main() Point A(1,2); f(A); ,36,函數

15、的返回值是對象,函數執(zhí)行完成返回調用者時。,Point g() Point A(1,2); return A; int main() Point B; B=g(); ,37,默認拷貝構造函數,如果程序員沒有定義類的拷貝構造函數,系統(tǒng)會在必要時自動生成一個默認的拷貝構造函數。它將初始值對象的每個數據成員的值都復制到新建立的對象中。,38,例:Point類,#include using namespace std; class Point public: Point(int xx=0, int yy=0) X=xx;Y=yy; Point(Point ,/形參為Point類對象的函數 void f

16、un1(Point p) coutp.GetX()endl; /返回值為Point類對象的函數 Point fun2() Point A(1,2); return A; ,void main() Point A(4,5); Point B(A); coutB.GetX()endl; fun1(B); B=fun2(); coutB.GetX()endl; ,39,賦值構造函數和拷貝構造函數的區(qū)別,當程序生成了對象副本時,編譯器都將使用復制構造函數。具體的說,當函數按值傳遞對象或函數返回對象時,都將使用復制構造函數。記住,按值傳遞意味著創(chuàng)建原始變量的一個副本。 c+ Primer Plus(第五

17、版)中文版中第385頁中寫道: 假設motto是一個StringBad對象,則下面4中聲明都將是調用復制構造函數(及拷貝構造函數): StringBad ditto (motto);/此語句前,ditto并不存在,本語句把motto作為參數,調用StringBad的拷貝構造函數來建立ditto StringBad metoo = motto; StringBad also = StringBad(motto); StringBad * pStringBad = new StringBad (motto); 以上4中方式都將調用:StringBad(const StringBad 使用了賦值操作

18、符,40,賦值構造函數和拷貝構造函數的區(qū)別:總結,賦值運算符和拷貝構造函數都是用已有的對象來創(chuàng)建另一個對象。不同之處在于:拷貝構造函數是生成一個全新的對象,即 A a (b);/這才是C+風格的初始化 A a = b;/注意,這種風格只是為了與C兼容 在這之前a對象是不存在的,或者說還沒有構造好。 賦值operator =()是兩個對象都已經構造好的情況下使用的。即 a = b; 的時候,a和b都已經初始化過了(這里的“初始化過”包括默認的構造函數初始化)。,41,3.9 靜態(tài)成員 (同類對象間的共享),問題的引入:如何在同類的多個對象間實現數據共享? 1.定義全局變量,但有缺陷 2.定義對象

19、之間共享的靜態(tài)變量。,42,3.9 靜態(tài)成員 (同類對象間的共享),3.9.1 靜態(tài)數據成員 例:分析 3.10,43,總結: 存在獨立性和持久性。靜態(tài)數據成員不隨對象的建立而分配空間,也不隨對象的撤銷而釋放。它是在程序編譯時,被分配空間,在程序結束時,才釋放空間。 初始化。只能在類體外進行初始化,不能用參數初始化表對靜態(tài)數據成員初始化。如果未初始化,則系統(tǒng)自動賦值為0。 格式: 數據類型 類名:靜態(tài)數據成員=初值; 例: int Box:height=10; 靜態(tài)數據成員既可以通過對象名引用,也可以通過類名引用。coutBox:heightendl; couta.heightendl; 如果

20、靜態(tài)數據成員被定義為私有的,則不能在類外直接引用,而必須通過公用的成員函數間接引用。,44,3.9.2 靜態(tài)成員函數,和靜態(tài)數據成員一樣,靜態(tài)成員函數是類的一部分,而不是對象的一部分。 靜態(tài)成員函數不是為了對象之間的溝通,而是為了能處理靜態(tài)數據成員。,45,3.9.2 靜態(tài)成員函數 例:3.11 提問: 靜態(tài)函數average()的聲明中可以去掉”static”嗎? 靜態(tài)成員函數為何不可以調用類的非靜態(tài)成員。,float Student:average() return(Student:sum/Student:count); coutThe average score of n student

21、s is stud0.average()endl;,靜態(tài)函數中沒有this指針,無法調用非靜態(tài)成員。,答:如果去掉static,則主函數中的代碼“Student:average()”出錯“illegal call of non-static member function”,即非靜態(tài)成員函數的調用要使用已有對象來調用,以便給this指針賦值。解決辦法:把主函數中的代碼“Student:average()”改成“stud0.average(),這樣做的前提是,stud0必須已經存在。,46,3.9.2 靜態(tài)成員函數,作用: (1)由于沒有this指針,可以把某些系統(tǒng)API的回調函數以靜態(tài)函數的形

22、式封裝到類的內部。比如你可以在類的內部寫一個線程函數供CreateThread創(chuàng)建線程用,如果沒有靜態(tài)函數,那么這種回調函數就必須定義成 全局函數,從而影響了OO的“封裝性”。 (2)可以封裝某些算法,比如數學函數,如ln,sin,tan等等,這些函數本就沒必要屬于任何一個對象,所以從類上調用感覺更好,比如定義一個數學函數類Math,調用Math:sin(3.14);如果非要用非靜態(tài)函數,那就必須: Math math; math.sin(3.14); 行是行,只是不爽:就為了一個根本無狀態(tài)存儲可言的數學函數還要引入一次對象的構造和一次對象的析構,當然不爽。而且既然有了對象,說不得你還得小心翼

23、翼的定義拷貝構造函數、拷貝賦值運算符等等,對于一些純算法的東西顯然是不合適的。 (3)總之,從OOA/OOD的角度考慮,一切不需要實例化就可以有確定行為方式的函數都應該設計成靜態(tài)的。,47,3.9.2 靜態(tài)成員函數 類外調用公用的靜態(tài)成員函數:類名 “:”或對象名。如:Box:volume(),a.volume() 使用后者并不意味著此函數屬于對象a,而只是用a的類型而已。 靜態(tài)成員函數可以直接引用本類中的靜態(tài)數據成員。 靜態(tài)成員函數沒有this指針,所以不能直接引用本類中的非靜態(tài)數據成員。 建議:只用靜態(tài)成員函數引用靜態(tài)數據成員,48,常成員函數和靜態(tài)成員函數的區(qū)別,靜態(tài)成員函數 stati

24、c 返回值類型 函數名(參數列表) 功能:管理靜態(tài)數據成員;提供類范圍的功能,即不需要對象來實現的功能。 常成員函數 返回值類型 函數名(參數列表)const 功能:由于數據封裝在類的內部,在處理一些問題的時候就需要小心翼翼,不能把成員數據破壞了。在類中,可以使用 const這個保留字來保護成員數據不被成員函數改變。,49,3.10 、友元(friend),問題的引入: 如果類以外的某個函數想訪問該類的成員變量,可行嗎?,回答:可行,可使該函數聲明為該類的朋友。,50,3.10.1 友元函數 如果一個類外的普通函數或其它類的成員函數,在類體中用friend對其進行聲明,則此函數稱為本類的友元函

25、數(但它并不是本類的成員)。 一個函數,可以被多個類聲明為友元函數。 1.將普通函數聲明為友元函數,51,#include using namespace std; class Time public: Time(int,int,int); private: int hour; int minute; int sec; ; Time:Time(int h,int m,int s)hour(h),minute(m),sec(s),void display(Time ,friend void display(Time ,error C2248: hour : cannot access priva

26、te member declared in class Time,52,結論:,友元可以訪問與其有友好關系的類中的私有數據。 友元包括友元函數與友元類。 友元沒有this指針.,提問:上列中display()不帶參數行嗎?,53,2.友元成員函數 friend函數不僅可以是一般函數,而且可以是另一個類中的成員函數。 例3.13 類的提前引用聲明(class Date),54,class Date public: Date(int,int,int); friend void Time:display(Date ,class Date public: Date(int,int,int); frie

27、nd Time; private: int month; int day; int year; ;,55,3.10.2 友元類 在A類的類體中,用friend聲明了B類,則稱B是A的友元類。類B的所有函數都是類A的友元函數。 格式: friend 類名; 友元的關系是單向的! 友元的關系不能傳遞!,56,一分鐘練習,一個類的友元函數或友元類可以訪問該類的(D) A. 私有成員 B. 保護成員 C. 公有成員 D. 所有成員 要把類FriendClass定義為類MyClass的友元類,則應在類MyClass的定義中加入語句_。,friend FriendClass,57,3.11 、類模板,問題

28、引入: 設計一個類,實現兩個整數、浮點數和字符的比較,求出最大數和最小數。,58,3.11 、類模板,目的:實現“一類多用”。適用于函數的參數個數相同而類型不同,且函數體相同的情況。 使用格式: 1、在類聲明前加上一行:template 2、用類模板定義對象時:類模板名 對象名(實參表列);,59,定義一個類,實現整數的相加 class Compare public: Compare(int a,int b) x=a;y=b; int max() return (xy)?x:y; int min() return (xy)?x:y; private: int x,y; ;,定義一個模板類實現整數、浮點數和字符的相加 Template class Compare public: Compare(numtype a, numtype

溫馨提示

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

評論

0/150

提交評論