




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、面向對象程序設計(二)呂俊白第八章對象生滅第八章對象生滅n主要內容:主要內容: 定義構造函數;定義構造函數; 構造函數的運行機制;構造函數的運行機制; 定義析構函數;定義析構函數; 析構函數的運行機制;析構函數的運行機制;n重點:重點:構造函數、析構函數。構造函數、析構函數。概述概述nC+的構造函數和析構函數是類的的構造函數和析構函數是類的特殊特殊成員成員函數,是為了保證類的封裝特性而設置的。在函數,是為了保證類的封裝特性而設置的。在程序設計中通過定義構造函數和析構函數能夠程序設計中通過定義構造函數和析構函數能夠輕松靈活地創建和撤消類對象。輕松靈活地創建和撤消類對象。當對象被建立時,構造函數馬
2、上被調用,自動當對象被建立時,構造函數馬上被調用,自動地給對象分配空間并進行初始化;地給對象分配空間并進行初始化;當對象生命期結束(撤消)時,析構函數由系當對象生命期結束(撤消)時,析構函數由系統自動調用,釋放對象所占有的資源。統自動調用,釋放對象所占有的資源。構造函數和析構函數完善了構造函數和析構函數完善了C+的類機制。的類機制。8.1 構造函數構造函數1為什么要引入構造函數為什么要引入構造函數n面向對象方法中的類是一組具有相同屬性和行面向對象方法中的類是一組具有相同屬性和行為的對象的抽象。為的對象的抽象。類描述的是一組事物所具有的共同性質。類描述的是一組事物所具有的共同性質。對象是類的實例
3、,是確實存在的實體,它具有對象是類的實例,是確實存在的實體,它具有確定的屬性。確定的屬性。由于對象的意義表達了現實世界的實體,它具有由于對象的意義表達了現實世界的實體,它具有確定的屬性,因此,一旦建立對象,就必須要確定的屬性,因此,一旦建立對象,就必須要有一個有意義的初始值。有一個有意義的初始值。2. 定義構造函數定義構造函數由于對象的一部分屬性(即類的一部分數據成員)由于對象的一部分屬性(即類的一部分數據成員)是私有的是私有的(private)(private)、被保護的、被保護的(protected)(protected),只允許類的成員函數來訪問它,所以,對象的只允許類的成員函數來訪問它
4、,所以,對象的初始化任務,必須由類的成員函數來完成。構初始化任務,必須由類的成員函數來完成。構造函數就是這樣一個特殊的成員函數。造函數就是這樣一個特殊的成員函數。 (1)構造函數的命名構造函數的命名構造函數名必須與類名相同。構造函數名必須與類名相同。 (2)定義構造函數定義構造函數我們可以象定義其它成員函數一樣定義構造函數。我們可以象定義其它成員函數一樣定義構造函數。即:即:構造函數可以在類的內部定義,也可以在構造函數可以在類的內部定義,也可以在類的外部定義。類的外部定義。例如:例如:(P:297)定義一個平面坐標類定義一個平面坐標類Ppoint,使用該類以計算坐標點的直,使用該類以計算坐標點
5、的直角坐標所對應的極坐標。(角坐標所對應的極坐標。(使用了頭文件衛士使用了頭文件衛士P:246)/ ppoint.h#ifndef HEADER_PPOINT#define HEADER_PPOINTclass PPoint double x, y; /直角坐標直角坐標public: PPoint(double ix, double iy); / 構造函數聲明構造函數聲明:設置坐標設置坐標 double xOffset(); /直角坐標直角坐標x分量分量 double yOffset(); /直角坐標直角坐標y分量分量 double angle(); /極坐標弧角極坐標弧角 double ra
6、dius(); /極坐標半徑極坐標半徑;/=#endif / HEADER_PPOINT / ppoint.cpp#includeppoint.h#includePPoint:PPoint(double ix, double iy) /構造函數定義構造函數定義 x=ix; y=iy; double PPoint:xOffset() return x;double PPoint:yOffset() return y;double PPoint:angle() return (180/3.14159)*atan2(y,x);double PPoint:radius() return sqrt(x*
7、x+y*y); / f0902.cpp using PPoint#includeppoint.h#includeusing namespace std;int main() for(double x,y; coutxy & x=0; ) PPoint p(x,y); coutangle=p.angle(), radius=p.radius(), x offset= p.xOffset(), y offset=p.yOffset()n; return 1;/= 注意:注意:1)C+規定:構造函數名必須與類名相同,規定:構造函數名必須與類名相同,它在該類對象創建時自動被調用。它在該類對象創
8、建時自動被調用。2)構造函數無返回類型。構造函數無返回類型。構造函數沒有返回類型,函數體中也不允構造函數沒有返回類型,函數體中也不允許包含返回值語句,但可以有無值返回許包含返回值語句,但可以有無值返回語句語句“return;”。例如:例如:class Person public: int Person() /return 1;/;錯誤:錯誤:1、構造函數是無返回類型的;、構造函數是無返回類型的; 2、構造函數體內只能使用無值返回語句、構造函數體內只能使用無值返回語句class Personpublic:Person()/正確正確 / return;/正確正確/;注意:注意:3)在類外部定義的構
9、造函數,其函數名前要加上在類外部定義的構造函數,其函數名前要加上“類名類名:”。4)直接以類名(構造函數名)調用構造函數,則直接以類名(構造函數名)調用構造函數,則產生一個無名對象。產生一個無名對象。例如:例如:PPoint(3,5);無名對象一般用在創建后不需要反復使用的場合,無名對象一般用在創建后不需要反復使用的場合,常在參數傳遞時用到。常在參數傳遞時用到。8.2構造函數的重載構造函數的重載/ f0903.cpp 構造函數重載構造函數重載#include#includeusing namespace std;class Date int year, month, day;public: D
10、ate(int y=2000, int m=1, int d=1); / 設置默認參數設置默認參數 Date(const string& s); / 重載重載 bool isLeapYear()const; void print();8.2.1重載構造函數重載構造函數n構造函數不但可以重載,還可以設置默認參數。構造函數不但可以重載,還可以設置默認參數。例如:例如: (P:299)Date:Date(const string& s) year = atoi(s.substr(0,4).c_str();/如:如: 2008-05-12 month = atoi(s.substr(5
11、,2).c_str(); day = atoi(s.substr(8,2).c_str();/-Date:Date(int y, int m, int d) year=y,month=m,day=d; bool Date:isLeapYear()const return (year % 4=0 & year % 100 )| year % 400=0;void Date:print() coutsetfill(0)setw(4)year-setw(2) month-setw(2)daynsetfill( );int main() Date c(2005-12-28); Date d(2
12、003,12,6); Date e(2002); / 默認兩個參數默認兩個參數 Date f(2002,12); / 默認一個參數默認一個參數 Date g; / 默認三個參數默認三個參數 c.print ();d.print ();e.print ();f.print ();g.print (); return 1;/=當處理過程不同時,使用當處理過程不同時,使用重載;當處理過程類似時,重載;當處理過程類似時,用默認參數可以省去一些用默認參數可以省去一些重復的編碼工作。重復的編碼工作。8.2.2無參數構造函數無參數構造函數n無參構造函數也稱默認構造函數,系統默認,類類型無參構造函數也稱默認構
13、造函數,系統默認,類類型定義中若無構造函數,照樣可以用對象定義語句創建定義中若無構造函數,照樣可以用對象定義語句創建對象。對象。即:類機制中總是為無構造函數的類默認地建立一個無即:類機制中總是為無構造函數的類默認地建立一個無參的構造函數,它除了分配對象的實體空間外,其他參的構造函數,它除了分配對象的實體空間外,其他什么也不做。什么也不做。例如:例如:class Date public: /類定義中無構造函數類定義中無構造函數 / 相當于定義了相當于定義了Date();int main() Date d; / ok / .n注意:注意:如果手工定義了無參構造函數,或者任何其如果手工定義了無參構造
14、函數,或者任何其他的構造函數,則系統不再提供默認的無參構造函數。他的構造函數,則系統不再提供默認的無參構造函數。例例1:class Date public: Date(int y, int m, int d) / .;int main() Date d; / error / .例例2:class A/私有成員私有成員public:A(int x)A(string s)/其他公有成員其他公有成員;/-A a(2);A c;/錯:錯:no appropriate default constructor available8.3類成員初始化類成員初始化8.3.1默認調用的無參數構造函數默認調用的無參
15、數構造函數n類定義中有數據成員和成員函數,數據類定義中有數據成員和成員函數,數據成員可以是內部數據類型的變量實體,成員可以是內部數據類型的變量實體,也可以是對象實體。也可以是對象實體。例如:有一個學號類和一個學生類,學生類中包例如:有一個學號類和一個學生類,學生類中包含了學號類的對象,這樣在構造學生類對象時,含了學號類的對象,這樣在構造學生類對象時,就面臨著學號類對象的構造。就面臨著學號類對象的構造。/ f0905.cpp 對象成員的默認構造對象成員的默認構造#include#include using namespace std;class StudentID/學號類學號類 int valu
16、e;public: StudentID( )/無參數構造函數無參數構造函數 static int nextStudentID = 0; /靜態局部變量靜態局部變量 value = +nextStudentID; coutAssigning student id valuen; ;/-class Student/學生類學生類 string name; StudentID id;/對象成員對象成員public: Student(string n = noName) cout Constructing student + n + n; name = n; ;/-int main() Student
17、s(Randy); return 1;/=nC+的類機制對于含有對象成員的類對象的的類機制對于含有對象成員的類對象的構造制定了一些規則,其內部的執行次序如下:構造制定了一些規則,其內部的執行次序如下:(1)分配對象空間;分配對象空間;(2)根據在類中聲明的根據在類中聲明的對象成員對象成員的次序依次調用的次序依次調用其構造函數;其構造函數;(3)執行自己的構造函數。執行自己的構造函數。8.3.2 成員的初始化成員的初始化n若要調用對象成員的有參構造函數,須顯式調用。其方若要調用對象成員的有參構造函數,須顯式調用。其方法為:法為:在構造函數的參數列表右括號后面,花括號前面,在構造函數的參數列表右括
18、號后面,花括號前面,用冒號引出構造函數的調用表。用冒號引出構造函數的調用表。例如:例如:/ f0907.cpp initialization of class members#include#include using namespace std;class StudentID int value;public: StudentID(int id=0) value=id; cout Assigning student id value endl; ;/-class Student string name; StudentID id;public: Student(string n=no nam
19、e, int ssID=0):id(ssID),name(n) coutConstructing student nn; ;/-int main() Student s(Randy, 98); Student t(Jenny); return 1;相當于:相當于:StudentID id(ssID);n對于常量成員和引用成員的初始化也可用構造對于常量成員和引用成員的初始化也可用構造參數表的方式解決。例如:參數表的方式解決。例如:P306.cpp#include using namespace std;class Silly const int ten;int &ra;public:Si
20、lly(int x,int &a):ten(x),ra(a)void print()coutten=ten,ra=raendl;int main() int a=20; Silly sy(10,a); sy.print(); return 1;小結:小結:n對于變量成員有兩種初始化方式:對于變量成員有兩種初始化方式:例如:例如:class Date int year, month, day;public: Date(int y=2000, int m=1, int d=1); / 設置默認參數設置默認參數 /;1.Date:Date(int y,int m,int d)year=y,m
21、onth=m,day=d;2.Date:Date(int y,int m,int d):year(y),month(m),day(d)8.4構造順序構造順序nC+給構造對象的順序做了專門的規定:給構造對象的順序做了專門的規定:局部對象局部對象v局部對象和靜態局部對象構造的順序與它們在程局部對象和靜態局部對象構造的順序與它們在程序中出現的順序是一致的。序中出現的順序是一致的。C+是根據運行中是根據運行中定義對象的順序來決定對象的創建順序,而且,定義對象的順序來決定對象的創建順序,而且,靜態局部對象只創建一次。靜態局部對象只創建一次。例如:例如:/ f0908.cpp/ test local ob
22、ject create order#includeusing namespace std;class Apublic: A() cout; ;/-class Bpublic: B() cout; ;/-class Cpublic: C() cout; ;/-void func() coutnfunc: ; A a; static B b; /靜態局部對象靜態局部對象 C c;/-int main() coutmain: ; for(int i=1; i=2; +i) for(int j=1; j=2; +j) if(i=2) C c; else A a; B b; func(); func()
23、; return 1;全局對象全局對象n和全局變量一樣,所有全局對象在主函數和全局變量一樣,所有全局對象在主函數(main)啟動之前全部已被構造。啟動之前全部已被構造。n全局對象的調試方法:全局對象的調試方法:(1)將全局對象先作為局部對象來調試;將全局對象先作為局部對象來調試;(2)在所有懷疑有錯的構造函數的開頭增加輸出在所有懷疑有錯的構造函數的開頭增加輸出語句語句n全局對象沒有明確的控制流來表明其構造順序。全局對象沒有明確的控制流來表明其構造順序。n全局對象的創建順序在標準全局對象的創建順序在標準C+中沒有規定,中沒有規定,一切視編譯器的內在特性而定。一切視編譯器的內在特性而定。例如:例如
24、:/ student.h#includeusing namespace std;class Student const int id;public: Student(int d):id(d) coutstudentn; void print() coutidn; ;/-class Tutor Student s;public: Tutor(Student& st):s(st) couttutorn; s.print(); ;/-/ f0909.cpp test global object create order#includestudent.hextern Student ra;/-
25、Tutor je(ra); /全局對象全局對象int main()return 1; / f09092.cpp test global object create order#includestudent.hStudent ra(18); /全局對象全局對象注意:注意:為了避免編譯器實現中的不確定問題,應盡為了避免編譯器實現中的不確定問題,應盡量不要設置全局對象,更不要讓全局對象之間互相量不要設置全局對象,更不要讓全局對象之間互相依賴。依賴。成員對象成員對象n成員對象以其在類中聲明的順序構造。成員對象以其在類中聲明的順序構造。例如:例如:/ f0910.cpp test member obje
26、ct create order#includeusing namespace std;class Apublic: A(int x) coutA:x; ;/-class Bpublic: B(int x) coutB:x; ;/-class C A a; B b;public: C(int x,int y):b(x),a(y) coutCn; ;/-int main() C c(15, 9); return 1;構造位置構造位置n全局對象、常對象、靜態對象都放在全全局對象、常對象、靜態對象都放在全局數據區;局數據區;n在函數中定義的局部對象,放在棧區;在函數中定義的局部對象,放在棧區;n用用n
27、ew申請的空間都在動態內存區(即申請的空間都在動態內存區(即堆區)。堆區)。8.5拷貝構造函數拷貝構造函數 (P:315)n拷貝構造函數是一種拷貝構造函數是一種特殊特殊的構造函數,具有一的構造函數,具有一般構造函數的所有特性。般構造函數的所有特性。n拷貝構造函數的拷貝構造函數的形參是本類對象的引用形參是本類對象的引用。n拷貝構造函數的作用是:使用一個已經存在的拷貝構造函數的作用是:使用一個已經存在的對象(由拷貝構造函數的參數指定的對象),對象(由拷貝構造函數的參數指定的對象),去初始化一個新的去初始化一個新的同類對象同類對象。用戶可以根據自己實際問題的需要定義特定的拷用戶可以根據自己實際問題的
28、需要定義特定的拷貝構造函數,以實現同類對象之間數據成員的貝構造函數,以實現同類對象之間數據成員的傳遞。傳遞。定義拷貝構造函數的一般形式為:定義拷貝構造函數的一般形式為:class 類名類名 public: 類名(形參表);類名(形參表);/構造函數構造函數 類名(類名類名(類名 對象名);對象名); /拷貝構造函數拷貝構造函數 ;類名類名:類名(類名類名(類名 對象名)對象名)/拷貝構造函數的實現拷貝構造函數的實現函數體函數體 另一常見的形式另一常見的形式: class 類名類名 public: 類名(形參表);類名(形參表);/構造函數構造函數 類名(類名(const 類名類名 對象名);對
29、象名); /拷貝構造函數拷貝構造函數 ; 類名類名:類名(類名(const類名類名 對象名)對象名)/拷貝構造函數的實現拷貝構造函數的實現函數體函數體 用用const限定引用的目的是限定引用的目的是:為了確保參數對象的所有數據成為了確保參數對象的所有數據成員值在拷貝構造函數體內不會被改變。員值在拷貝構造函數體內不會被改變。#include using namespace std;class Point public:Point (int xx=0,int yy =0);Point(const Point &p);/聲明拷貝構造函數聲明拷貝構造函數int GetX( ) return X
30、;int GetY( ) return Y;private: int X,Y;Point:Point (int xx,int yy)X=xx;Y=yy;cout構造函數被調用構造函數被調用endl;Point:Point(const Point &p)/拷貝構造函數的實現拷貝構造函數的實現X=p.X;Y=p.Y;cout拷貝構造函數被調用拷貝構造函數被調用endl;例如:例如:Copy_Constructor.cpp注意:注意:普通構造函數是在對象創建時被調用,而普通構造函數是在對象創建時被調用,而拷貝構拷貝構造函數在以下三種情況下都會被調用:造函數在以下三種情況下都會被調用:(1)當
31、用類的一個對象去初始化該類的另一個對當用類的一個對象去初始化該類的另一個對象時。象時。int main( )Point A(1,2);Point B(A);cout對象對象B的的X坐標:坐標:B.GetX()endl;return 1;(2)如果如果函數的形參是類的對象函數的形參是類的對象,調用函數,進,調用函數,進行形參和實參結合時。行形參和實參結合時。void f(Point p)coutp.GetX()endl;int main()Point A(1,2);f(A);return 1;(3)如果如果函數的返回值是類的對象函數的返回值是類的對象,函數調用完,函數調用完成返回時。成返回時。P
32、oint g() Point A(1,2);return A;int main()Point B;coutCalling g.endl;B=g();return 1;n如果程序員沒有為類聲明拷貝構造函數,則編如果程序員沒有為類聲明拷貝構造函數,則編譯器自己生成一個拷貝構造函數。譯器自己生成一個拷貝構造函數。n該構造函數的功能是:該構造函數的功能是:把參數對象的每個數據把參數對象的每個數據成員的值都復制到新建立的對象中。成員的值都復制到新建立的對象中。例如:例如:/ f0912_modi.cpp constructing object from other object#includeusing
33、 namespace std;class Person char* pName;/P:315圖圖9-3public: Person(char* pN=noName) coutConstructing pNn; pName = new charstrlen(pN)+1; if(pName) strcpy(pName,pN); void print() coutName:pNameendl;/-int main() Person p1(Randy); Person p2(p1); p2.print(); return 1;修改修改/ f0912_modi.cpp constructing obje
34、ct from other object(新增析構函數)(新增析構函數)#includeusing namespace std;class Person char* pName;public: Person(char* pN=noName) coutConstructing pNn; pName = new charstrlen(pN)+1; if(pName) strcpy(pName,pN); void print() coutName:pNameendl;Person()/析構函數析構函數 cout Destructing pNamen; delete pName; ;/-int mai
35、n() Person p1(Randy); Person p2(p1); p2.print(); return 1;原因:析構原因:析構p2時將存有時將存有Randy的空間先行釋放了,輪到析的空間先行釋放了,輪到析構構p1時,時,Randy已經不復存在了。已經不復存在了。/ f0913.cpp copy constructor#includeusing namespace std;class Person char* pName;public: Person(char* pN=noName) coutConstructing pNn; pName = new charstrlen(pN)+1; if(pName) strcpy(pName,pN); Person(const Person& s)/拷貝構造函數拷貝構造函數 coutcopy Construct
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工業管道焊縫的檢測方法與案例
- 工業自動化技術的現狀與趨勢
- 工業設計在產品開發中的作用
- 工業設計新品的創新與市場分析
- 工業節能的挑戰與解決方案
- 工作壓力的緩解與管理
- 工作環境優化與員工滿意度提升
- 工程中的環境保護法規與實踐
- 工程師培訓中的數據可視化技術
- 工廠設備安全與維護管理
- 《 大學生軍事理論教程》全套教學課件
- 無線電裝接工考試:初級無線電裝接工考試題庫(題庫版)
- 石家莊市國企招聘考試真題題庫2024版
- 探索神奇的植物世界智慧樹知到期末考試答案章節答案2024年成都師范學院
- 2024-2030年中國機器人關節模組行業市場競爭態勢及前景戰略研判報告
- 實驗室儀器設備等采購項目培訓方案
- 三江學院輔導員考試試題2024
- UASB+SBR處理果汁廢水設計說明書及圖紙
- 華圖教育:2024年國考面試白皮書
- 2024年海港區社區工作者招聘筆試沖刺題(帶答案解析)
- 國開2024春專科《高等數學基礎》形考任務1-4試題及答案
評論
0/150
提交評論