構造和析構函數_第1頁
構造和析構函數_第2頁
構造和析構函數_第3頁
構造和析構函數_第4頁
構造和析構函數_第5頁
已閱讀5頁,還剩36頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第五章 構造和析構函數 構造和析構函數classStudent{public:Student();//構造函數的聲明;系統約定與類同名,自動調用,沒有返回值,可以重載~Student();//析構函數的聲明;沒有參數,沒有返回值,不可以重載;對象生命期結束時由系統自動調用protected: char*name;intage;};Student::Student(){cout<<"構造"<<endl;age=5;}Student::~Student(){cout<<“析構,對象結束了"<<endl;}intmain(){ Studenta;Studentb;return0;}析構函數的調用順序和對象構造的順序相反析構函數不是刪除對象,而是在撤銷對象占用的內存之前完成一些清理工作。還可以用來執行用戶希望在對象生命期結束時所執行的任何操作。2

C++標準庫--stringstringname;自動處理空間的占用問題。可以用=進行賦值操作,==進行比較,+做串聯.使用時#include<string>

stringstr1,str2=“abcd”;

str1=str2;

str2=str1+”123”;

cout<<str2<<""<<str2.length();由C++字符串得到對應的C_string的方法是使用data()、c_str()chars[20];strcpy(s,str1.data());strcpy(s,str2.c_str()); 帶參數的構造函數

classStudent{ public:

Student(stringpName,inti,floatj){

cout<<"構造學生"<<pName<<endl;

name=pName;

semesHours=i;

gpa=j;

}

~Student()

{cout<<"析構"<<name<<endl;} private:

stringname;intsemesHours;floatgpa;

};

voidf(){Studentt("Tom",17,90);}

intmain(){

Studentss("Jenny",20,80.5);

f();

return0;

} 構造和析構函數classA{public: ints;};Aa1;對于沒有顯性構造函數的類系統都自動提供一個默認構造函數

A(){}用戶沒有定義析構函數,編譯器自動生成一個析構函數。

~A(){} 構造函數重載classStudent{

public:

Student(stringpName){

cout<<"姓名"<<pName<<endl;

name=pName;

}

Student(stringpName,inti){

cout<<“姓名學時"<<endl;

name=pName;

semesHours=i;

}

Student(){}//自定義無參構造函數將替代缺省構造函數的存在

private:

stringname;intsemesHours;

};

intmain(){

Studenttt("Tom",60);Studentss("Jenny");

Studentf;

return0;

}如果手工定義了任何的構造函數,系統不再提供默認的無參構造函數。 默認值構造函數classStudent{public:

Student(stringpName=“”,inti=0){

cout<<“姓名學時"<<endl;

name=pName;

semesHours=i;

}protected:

stringname;intsemesHours;};intmain(){

Studenttt("Tom",60);Studentss("Jenny");

Studentf;//不錯誤return0;}無名對象(一次性對象):Student("Jane");一般作為實參,用在創建后不需要反復使用的場合 構造函數構造函數是特殊的類成員函數。C++規定與類同名的成員函數是構造函數,在該類的對象創建時,自動被調用。構造函數負責對象的初始化可擁有多個參數。可以重載。構造函數不返回具體的值,不指定函數的返回類型。可內置定義,也可以在類外定義。通常是Public的 析構函數析構函數也是一個特殊的成員函數;作用與構造函數相反;在對象的生命期結束時自動被調用。名字是類名前加一個~;不返回任何值;沒有函數類型,沒有函數參數,因此不能被重載。一個類可以由多個構造函數,只能有一個析構函數。可內置定義,也可以在類外定義。用于清理和釋放資源的工作。通常是Public的 練習題判斷對錯,錯誤寫出原因:1、使用struct定義的類中默認的訪問權限是private的2、this不能被非成員函數訪問3、任何情況下private權限的內容不能被類外訪問4、引用破壞了函數的封裝性5、內聯函數的作用是提高系統的效率6、不同類的成員函數也可以重載7、參數類型、函數返回類型可以作為函數重載的依據 組合類組合:是指結構和類的聲明嵌入結構變量和對象作為其成員的現象嵌入的對象成員稱為成員對象(類成員)包容這個成員對象的類稱為組合類 組合類創建classStudent{public:

Student(){

cout<<"constructingstudent.\n";

semesHours=100;}~Student(){cout<<“~Student\n”;}protected:

intsemesHours;};classTeacher{public:

Teacher(){cout<<"constructingteacher.\n";}

~Teacher(){cout<<“~Teacher\n”;}private:

charname[20];};classTutorPair{public:

TutorPair(){

cout<<"constructingtutorpair.\n";

noMeetings=0;

}

~TutorPair(){cout<<“~TutorPair\n”;}protected:

Studentstudent;

Teacherteacher;

intnoMeetings;};intmain(){

TutorPairtp;

cout<<"backinmain.\n";return0;} 組合類對象的初始化困惑classStudentID{public:

StudentID(intid=0){

value=id;

}

~StudentID(){}protected:

intvalue;};classStudent{public:

Student(stringpName="noName",intssID=0){name=pName;

}private:

stringname;

StudentIDid;};intmain(){

Students("Randy",9818);

return0;} 組合類的構造函數classStudentID{public:

StudentID(intid=0){

value=id;

}

~StudentID(){}protected:

intvalue;};classStudent{public:

Student(stringpName="noName",intssID=0):id(ssID){name=pName;

}private:

stringname;

StudentIDid;};intmain(){

Students("Randy",9818);

return0;}冒號語法:用冒號引出構造函數的調用表(初始化列表),用構造參數列表中說明的參數去調用構造函數 例子classStudent{public:

Student(inti){

cout<<"constructingstudent.\n";

semesHours=i;}~Student(){cout<<“~Student\n”;}protected:

intsemesHours;};classTeacher{public:

Teacher(stringp){

cout<<"constructingteacher.\n"; name=p; }

~Teacher(){cout<<“~Teacher\n”;}private: stringname;};classTutorPair{public:

TutorPair(inti,intj,stringp): teacher(p),student(j){

cout<<"constructingtutorpair.\n";

noMeetings=i;

}

~TutorPair(){cout<<“~TutorPair\n”;}protected:

Studentstudent;

Teacherteacher;

intnoMeetings;};intmain(){

TutorPairtp(5,20,"Tim");

cout<<"backinmain.\n";return0;} 構造函數初始化常數據成員和引用成員 classStudent{public:

Student(ints,int&k):i(s),j(k)

{}//不可以直接賦值

voidp(){cout<<j<<endl;}protected:

constinti;

int&j;};intmain(){

intc=123;

Students(9818,c);

s.p();

return0;} 對象構造順序局部和靜態局部對象(文件作用域)以文本定義順序為順序,(類成員屬于此種情況)靜態對象在首次定義時構造一次;程序結束析構全局對象在main之前構造;程序結束時析構全局對象如果分布在不同文件中,則構造順序隨機 例子classA{public: A(intk){s=k;cout<<k<<"Aisconstructing\n";}; ~A(){cout<<s<<"~A\n";} ints;};intmain(){

cout<<"mainisrunning\n";

As(1);voidf();f();f();

return0;}voidf(){

cout<<"fisrunning\n";

As(2);

staticAt(3);}At(4); 練習重寫Rectangle,將坐標抽象為Point類,通過冒號語法對Rectangle中的Point類進行初始化 為對象申請動態空間Malloc和對應的free函數不能調用構造函數和析構函數,這破壞了:空間分配、初始化的功能。所以引入了new和delete。因為空間不確定才使用堆空間函數內部的申請空間要及時釋放,否則容易造成內存泄漏 malloc\newclassaa{public:aa(inta=1){id=a;cout<<"構造"<<endl;}intid;~aa(){cout<<“aais析構.”<<endl;}};intmain(){

aa*p=newaa(9);

cout<<p->id;

aa*q=(aa*)malloc(sizeof(aa));

cout<<q->id;//隨機數,表明構造函數未調用

deletep;

free(q);//析構函數未調用

return0;} 例子classaa{public:aa(inta=1){id=a;}intid;};aa&m(){

aa*p=newaa(9);

return(*p);}intmain(){

aa&s=m();

cout<<s.id;//結果為9表明沒有釋放

return0;} 例子classaa{public:aa(inta=1){id=a;}intid;};aa&m(){

aa*p=newaa(9);

deletep;//釋放后不應該再返回

return(*p);}intmain(){

aa&s=m();

cout<<s.id;//結果為隨機數表明被釋放

return0;} 析構函數的需要性classaa{public:aa(inta=9){age=newint[a];}

~aa(){delete[]age;}

int*age;};intmain(){

aa*s=newaa;

s->age[0]=20;

int*t=s->age;

deletes;

cout<<t[0];

return0;} 對象數組classStudent{public:

Student(){cin>>value;}

~Student(){cout<<value<<endl;}protected:

intvalue;};intmain(){

Student*p=newStudent[5];

cout<<“DeleteBegin”<<endl;

delete[]p;

return0;}對象數組不能通過參數傳遞初始化。要么默認構造函數,要么構造函數有默認參數Studenta[10](20);//錯誤

建立動態數組intnextStudentID=1;classStudentID{public:StudentID(){ value=nextStudentID++;}~StudentID(){--nextStudentID;}protected:intvalue;};classStudent{public:Student(stringpName="noName"){name=pName;}protected:stringname;StudentIDid;};intmain(){ inti,

j; stringtemp; cin>>i; Student**p=newStudent*[

i

]; for(j=0;j<i;j++){ cin>>temp; p[j]=newStudent(temp); cout<<nextStudentID;

}

for(j=i-1;j>=0;j--)

deletep[j]; delete[]p; cout<<nextStudentID;

return0;} 例子

inti;inta[i];//error

inti;

cin>>i;

int*p=newint[i];delete[]p; 對象的賦值classStudent{ stringname;intsemesHours;public: Student(stringpName=“”,inti=0){

name=pName;semesHours=I;

}};Studenta("jenny",50);Studentb;b=a;一個已知對象賦值給另一個已知對象,通過對賦值運算符的重載實現的

Student&operator=(constStudent&rValue){

name=rV;

semesHours=rValue.semesHours;

return*this;} 對象的拷貝用一個已知對象構造(初始化)一個新對象。 Students1(“Jenny”);

Students2=s1;即Students2(s1);

Studentfn(Students){Studentk;//.......;returnk}//window下 intmain(){ Studentm,n;

n=fn(m);return0; }拷貝構造函數

Student(constStudent&s){

name=;semesHours=s.semesHours;

}

例子-練習,調用哪個函數classStudent{public: Student(intk):i(k){}

Student(){} voidp(){cout<<i<<endl;}protected: inti;};intmain(){

Students(9818);

s.p(); Studentt(s); t.p();

Studentm;

m=t;

m.p();

return0;} 重寫拷貝構造函數classStudent{public: Student(intk):i(k){}

Student(){} voidp(){cout<<i<<endl;}

Student(Studentconst&m){i=m.i*(-1);}//重寫拷貝構造函數protected: inti;};intmain(){

Students(9818);s.p();Studentt(s);t.p(); Studentk=s;k.p(); Student*p=newStudent(s); p->p(); Studentm;m=s; m.p();return0;} 淺拷貝classaa{public:aa(){ f=newchar[10]; }~aa(){delete[]f;}char*f;};intmain(){ aap; strcpy(p.f,"Computer"); cout<<p.f<<endl; aaq(p);//aaq=p; cout<<q.f<<endl; strcpy(p.f,"Software"); cout<<q.f<<p.f<<endl;

return0;}創建q時,對象p被復制給了q,但資源未復制,使得p和q指向同一個資源,這稱為淺拷貝同一個指針執行兩遍delete操作,會發生什么?災難,可能會破壞該堆及自由內存表 深拷貝classaa{public: aa(){f=newchar[10];} aa(aaconst&s){

f=newchar[10];strcpy(f,s.f);} ~aa(){delete[]f;} char*f;};intmain(){ aap; strcpy(p.f,"Computer"); cout<<p.f<<endl; aaq(p); cout<<q.f<<endl; strcpy(p.f,”Software”); cout<<p.f<<q.f<<endl; return0;} 例子-練習classStudent{public: Student(inti){value=i;cout<<"Student"<<value<<endl;} ~Student(){cout<<"~Student"<<value<<endl;}protected: intvalue;};intmain(){ Student(9); Student*p=&Student(8); Student&q=Student(7); Studenti(6); i=Student(5);

return0;} 類型轉換classaa{public:aa(inta=1){id=a;cout<<"構造"<<endl;}aa(constaa&s){id=s.id;cout<<"拷貝"<<endl;}int&Getid(){return(id);}private:intid;};intmain(){ aam;//“構造” aan(m);//“拷貝” aao=m;//“拷貝”和aao(m)等價

aas=9;//“構造”和aas(9)等價 aat;//“構造”

t=9;//“構造”、賦值運算

return0;} 類型轉換classaa{public:aa(inta=1){id=a;}char*p;intid;};voidm(aaa){cout<<a.id<<endl;}intmain(){m(9);//相當于m(aa(9));return0;}如果存在m(int)的函數則優先匹配 類型轉換classaa{public:aa(inta=1){id=a;}intid;};classbb{public:bb(inta=2){id=a;}intid;};voidm(aaa){cout<<a.id<<endl;}voidm(bba){cout<<a.id<<endl;}intmain(){

m(9);//存在二義性;

return0;} 類型轉換classHighWorker{floatincome;public:HighWorker(floata=2000.0){income=a;}floatGetincome(){return(income);}};classWorker{floatincome;public:Worker(fl

溫馨提示

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

評論

0/150

提交評論