版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
類與對象C語言程序設(shè)計目錄content類的實例化——對象1類的構(gòu)造函數(shù)和析構(gòu)函數(shù)2new和delete3this指針4拷貝構(gòu)造函數(shù)5運算符重載6類的特殊成員7對象成員8對象數(shù)組與對象指針9友元0112.1類的實例化——對象
面向?qū)ο蟪绦蛟O(shè)計的基本單元是對象,通過對諸多同類型的對象進行抽象得到class類的聲明,再使用該class類類型創(chuàng)建多個不同的對象,具有class類型的變量被稱作該類的對象,又叫該類的實例。StudentmyStudent;例如myStudent對象的內(nèi)存映像
數(shù)據(jù)空間代碼空間使用運算符“.”來訪問對象的成員12.1類的實例化——對象例Studenta,b;a.registerStudent(“Tom”,”123456”,20);b.registerStudent(“Jerry”,”123457”,20);a.show();b.show();既然所有對象共享同一個代碼空間,系統(tǒng)是如何區(qū)分某個成員函數(shù)代碼到底在處理哪個對象的數(shù)據(jù)呢?(this指針見12.4)12.2
類的構(gòu)造函數(shù)和析構(gòu)函數(shù)構(gòu)造函數(shù):在創(chuàng)建對象時,編譯器自動調(diào)用類的構(gòu)造函數(shù),自動地進行數(shù)據(jù)成員的初始化。析構(gòu)函數(shù):類對象退出它的作用域時,編譯器會自動調(diào)用析構(gòu)函數(shù)來處理善后工作。優(yōu)點:1)簡化對象的初始化2)減少人為失誤造成的設(shè)計漏洞,如:內(nèi)存泄漏classStudent{private:charname[20];charid[15];intage;public:Student(constchar*n,constchar*i,inta);voidshow();};Student::Student(constchar*n,constchar*i,inta){strcpy(name,n);strcpy(id,i);age=a;}12.2.1構(gòu)造函數(shù)下面為Student類定義一個構(gòu)造函數(shù)Student(),用它來初始化數(shù)據(jù)成員。1)構(gòu)造函數(shù)與類同名,不能為其制定任何返回類型2)當對象被創(chuàng)建時,構(gòu)造函數(shù)被自動調(diào)用。intmain(){StudentmyStudent(“Tom”,“123456”,20);//創(chuàng)建Student類的對象myStudentreturn0;}12.2.2
重載構(gòu)造函數(shù)和缺省構(gòu)造函數(shù)例classmyClass{private:inta,b;public:myClass();myClass(inti,intj);voidshow();};myClass::myClass(){cout<<“執(zhí)行myClass()”<<endl;a=0,b=0;}myClass::myClass(inti,intj){cout<<“執(zhí)行myClass(int,int)”<<endl;a=i,b=j;}intmain(){myClassob1;myClassob2(10,5);return0;}當執(zhí)行語句myClassob1時,調(diào)用第一種不帶參數(shù)的缺省構(gòu)造函數(shù),而當執(zhí)行語句myClassob2(10,5)時,調(diào)用第二種帶2個整型參數(shù)的重載構(gòu)造函數(shù)12.2.2
重載構(gòu)造函數(shù)和缺省構(gòu)造函數(shù)幾點說明:(1)定義對象ob1時語句為myClassob1;不能寫成:myClassob1();(2)當我們沒有為Student類定義任何構(gòu)造函數(shù)時,編譯器會自動為該類創(chuàng)建一個不帶參數(shù)的構(gòu)造函數(shù),即缺省構(gòu)造函數(shù)。且只能這樣定義該類的對象:StudentmyStudent;(3)強烈建議讓每個類都擁有一個不帶參數(shù)的構(gòu)造函數(shù),即使這個構(gòu)造函數(shù)為空。這樣在使用對象數(shù)組和創(chuàng)建派生類對象時不會發(fā)生不必要的麻煩。(4)如果一個構(gòu)造函數(shù)的所有參數(shù)均帶有缺省值,那么這個構(gòu)造函數(shù)本質(zhì)上和缺省構(gòu)造函數(shù)有等同的作用,原因在于調(diào)用它時可以不必傳遞任何參數(shù)。此時當然還可以再定義不帶參數(shù)的構(gòu)造函數(shù)了,但是如果在創(chuàng)建對象時采用了不傳遞任何參數(shù)的方式,因為會產(chǎn)生歧義,編譯器將無法確定是調(diào)用定義了缺省值的構(gòu)造函數(shù),還是調(diào)用不帶任何參數(shù)的構(gòu)造函數(shù),此時編譯器將提示出錯12.2.3析構(gòu)函數(shù)每當撤銷一個對象時,析構(gòu)函數(shù)就會自動調(diào)用。撤銷對象分為兩種場景:對象在離開其作用域時,以及用new運算符創(chuàng)建的動態(tài)對象在使用delete運算符操作時。例如classmyClass{private:inta,b;public:myClass();~myClass();
…};
…myClass:~myClass(){cout<<“執(zhí)行析構(gòu)函數(shù)”<<endl;}析構(gòu)函數(shù)voidmain(){myClassob;cout<<”main()函數(shù)運行結(jié)束!”<<endl;}運行情況如下:main()函數(shù)運行結(jié)束執(zhí)行析構(gòu)函數(shù)12.2.3析構(gòu)函數(shù)幾點說明:(1)析構(gòu)函數(shù)必須和類同名,并且在函數(shù)名前面加上一個~字符;(2)析構(gòu)函數(shù)不能帶任何參數(shù),因此,不能對析構(gòu)函數(shù)進行重載;也不能為析構(gòu)函數(shù)指定任何返回類型,即使void也不行;(3)每當對象撤銷時,總要先自動執(zhí)行析構(gòu)函數(shù)。如果沒有顯式地定義類的析構(gòu)函數(shù),系統(tǒng)也會自動加上缺省析構(gòu)函數(shù),但函數(shù)體為空12.2.3析構(gòu)函數(shù)例類Chunk的構(gòu)造函數(shù)Chunk()動態(tài)分配一塊大小為size的堆內(nèi)存,析構(gòu)函數(shù)負責釋放這塊堆內(nèi)存classChunk{private:void*p;public:Chunk(unsignedintsize=0);~Chunk();};Chunk::Chunk(unsignedintsize){p=newchar[size];//分配一個char型的數(shù)組空間,該數(shù)組有size個元素}Chunk::~Chunk(){delete[]p;//釋放分配的size個char型元素空間}12.2.3析構(gòu)函數(shù)幾點說明:(1)析構(gòu)函數(shù)只負責回收以前在創(chuàng)建對象時在構(gòu)造函數(shù)中分配的動態(tài)堆內(nèi)存,以及在對象生存期間通過對象的其它成員函數(shù)分配的動態(tài)堆內(nèi)存。而不是指類對象本身所占的內(nèi)存空間。因為,析構(gòu)函數(shù)本身代碼就是對象的一部分,其占據(jù)對象一部分內(nèi)存空間,本身代碼的執(zhí)行不能回收自身所占的內(nèi)存空間。(2)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的時機:局部對象在程序執(zhí)行到它的定義語句時創(chuàng)建,調(diào)用構(gòu)造函數(shù);在退出它的作用域時撤銷該對象,調(diào)用析構(gòu)函數(shù);全局對象在程序執(zhí)行主函數(shù)main之前創(chuàng)建,在整個程序執(zhí)行結(jié)束時撤銷;對于用new運算符動態(tài)創(chuàng)建的對象,當創(chuàng)建時調(diào)用構(gòu)造函數(shù),使用delete運算符釋放該對象時調(diào)用析構(gòu)函數(shù)。若不通過delete顯式地釋放動態(tài)對象,那么程序?qū)⒉粫詣俞尫旁搶ο蟆?2.3new和delete例voidmyfun(){int*pi=NULL;//通常指針未明確建立指向前,賦值NULL,處于“休息”態(tài)pi=newint;//注意對比:pi=(int*)malloc(sizeof(int));if(pi==NULL)//如果內(nèi)存中沒有足夠的動態(tài)內(nèi)存,則返回NULL指針{ cout<<“內(nèi)存不足”<<endl; exit(1);}*pi=10;cout<<*pi<<endl;deletepi;//注意對比:free(pi);pi=NULL;//一旦釋放空間,使用權(quán)交回系統(tǒng),但pi的指向不變,成為//危險的“野指針”。為了安全,將賦值NULL,處于“休息”態(tài)}12.3new和delete幾點說明:(1)new運算符可以動態(tài)分配一個數(shù)據(jù)空間,也可以動態(tài)分配數(shù)組空間。delete運算符與new運算符配合使用,用來釋放已分配的內(nèi)存空間。如果用new分配的是一個數(shù)組,那么最好用delete[]來釋放;12.3new和delete(2)malloc和free等庫函數(shù)和new和delete運算符的區(qū)別:a)由于malloc/free是庫函數(shù)而不是運算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強加于malloc/free。b)對于內(nèi)部數(shù)據(jù)類型(比如:int)的“對象”沒有構(gòu)造與析構(gòu)的過程,對它們而言malloc/free和new/delete是等價的。c)為什么C++不把malloc/free淘汰出局呢?這是因為C++程序經(jīng)常要調(diào)用C函數(shù),而C程序只能用malloc/free管理動態(tài)內(nèi)存。另外,malloc/free功能還有一好處,就是可以和realloc組合使用,在需要擴大內(nèi)存塊時不一定會導致內(nèi)存移動;而用new/delete實現(xiàn)時只能用new[]-copy-delete[]操作序列完成,每次都會導致內(nèi)存移動。(3)new/delete也可以用于創(chuàng)建和銷毀對象。當使用new運算符創(chuàng)建動態(tài)對象后,使用delete運算符操作時會銷毀對象,此時析構(gòu)函數(shù)會自動調(diào)用。這是析構(gòu)函數(shù)自動調(diào)用的第二種場景12.4this指針當成員函數(shù)被調(diào)用時,會有一個隱含的參數(shù)自動傳遞給該函數(shù),這個隱含的參數(shù)是一個指向調(diào)用該成員函數(shù)對象的指針,叫做this指針。例classComplex{private:doublereal,imag;public:voidset(doubler,doublei);voidshow();Complexadd(Complex&c);};voidComplex::set(doubler,doublei){real=r,imag=i;}voidComplex::show(){cout<<“real=”<<real<<‘,’<<“imag=”<<imag<<endl;}ComplexComplex::add(Complex&c){Complextemp;temp.real=real+c.real;temp.imag=imag+c.imag;returntemp;}intmain(){Complexob1,ob2,sum;ob1.set(1,3.5);ob2.set(10.5,4);sum=ob1.add(ob2);sum.show();return0;}加法運算是在兩個Complex對象之間進行,運算結(jié)果是第三個Complex對象。但是成員函數(shù)add卻只有一個參數(shù)c,這是為什么呢?原來,成員函數(shù)add還有一個隱含的參數(shù)this,它是被自動傳遞給add函數(shù)的。this指針指向當前調(diào)用add函數(shù)的對象。相當于:ComplexComplex::add(Complex*constthis,Complex&c){Complextemp;temp.real=this->real+c.real;temp.imag=this->imag+c.imag;returntemp;}12.4this指針幾點說明:(1)this指針是指向調(diào)用成員函數(shù)的對象指針,它的類型是:類名*constthis;由此可見,this指針是常量指針,在程序里不能直接給this賦值,但是可以給this指向的對象賦值:*this=…;(2)在成員函數(shù)中可以顯式引用this指針;當成員函數(shù)的形參標識符與類的數(shù)據(jù)成員同名時,需要使用this指針“顯式”地指明數(shù)據(jù)成員以示區(qū)分。但這種情況應盡量避免,以提高程序的可讀性。12.5拷貝構(gòu)造函數(shù)拷貝構(gòu)造函數(shù):對于同class類型的兩個對象,可以他們之間使用拷貝構(gòu)造函數(shù)相直接整體賦值例classComplex{private:doublereal,imag;public:Complex(constdoubler=0,constdoubleii=0);voidShow();};Complex::Complex(constdoubler,constdoubleii){real=r,imag=ii;}voidComplex::Show(){cout<<“實部=”<real<<‘’<<“虛部=”<<imag<<endl;}intmain(){Complexob1(5.8,10.5);Complexob2(ob1); //調(diào)用缺省拷貝構(gòu)造函數(shù)ob2.Show();return0;}程序運行結(jié)果:實部=5.8虛部=10.5
也可以直接利用賦值運算符:Complexob2=ob1;12.5this指針幾點說明:(1)缺省拷貝構(gòu)造函數(shù)是在類中沒有拷貝構(gòu)造函數(shù)時編譯器自動加進類中,它負責實現(xiàn)“逐域”地拷貝對象的數(shù)據(jù)。(2)盡管拷貝構(gòu)造函數(shù)和賦值運算符(=)都是把一個對象的數(shù)據(jù)拷貝到另一個同類型對象,但二者是有區(qū)別的:拷貝構(gòu)造函數(shù)用來創(chuàng)建新對象并完成對該對象數(shù)據(jù)成員的初始化;而賦值運算符則是用來改變一個已有對象的值。12.5.2自定義拷貝構(gòu)造函數(shù)類名([const]類名&參數(shù)名);一般形式classLocation{public:Location(intxx=0,intyy=0){X=xx;Y=yy;cout<<“Objectconstructed.”<<endl;}Location(Location&p);~Location(){cout<<X<<“,”<<Y<<“Objectdestroyed.”<<endl;}intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};Location::Location(Location&p){X=p.X;Y=p.Y;cout<<“Copy_constructorcalled.”<<endl;}main(){LocationA(1,2);LocationB(A); //自定義的拷貝構(gòu)造函數(shù)被調(diào)用cout<<“B:”<<B.GetX()<<“,”<<B.GetY()<<endl;}例12.5.2自定義拷貝構(gòu)造函數(shù)例
如果類不含指針類型的數(shù)據(jù)成員,那么缺省拷貝構(gòu)造函數(shù)“逐域”地拷貝已存在的對象來初始化被創(chuàng)建的新對象是不會出錯的。但如果類中包含指針類型的數(shù)據(jù)成員,則會產(chǎn)生運行錯誤。classMessage//類Message用來保存一個消息串{private:char*buffer;//數(shù)據(jù)成員buffer指向被保存的消息串public:Message(constchar*str);~Message();voidshow();};Message::Message(constchar*str){buffer=newchar[strlen(str)+1];//堆區(qū)內(nèi)存的分配if(buffer!=0)strcpy(buffer,str);}Message::~Message(){delete[]buffer;//堆區(qū)內(nèi)存的回收}intmain(){Messageob1(“Hello”);Messageob2(ob1);//產(chǎn)生運行錯誤return0;}12.5.2自定義拷貝構(gòu)造函數(shù)由于這個缺省拷貝構(gòu)造函數(shù)僅僅完成簡單的“逐域”拷貝工作,這就是常說的“淺拷貝”。于是ob1.buffer和ob2.buffer指向同一塊內(nèi)存空間。
當撤銷對象ob2時,執(zhí)行析構(gòu)函數(shù),將釋放ob2.buffer所指向的堆內(nèi)存空間。接著系統(tǒng)又要撤銷ob1,同樣要執(zhí)行一次析構(gòu)函數(shù),也要釋放ob1.buffer所指向的堆內(nèi)存空間。同一塊內(nèi)存空間被釋放兩次,導致運行錯誤。針對上述情況,應該定義自己的拷貝構(gòu)造函數(shù)來實現(xiàn)“深拷貝”。12.6運算符重載C++中預定義的運算符操作對象只能是基本數(shù)據(jù)類型,對于許多用戶自定義類型(例如類),也需要類似的運算操作。這時就必須在C++中重新定義這些運算符,運算符重載的實質(zhì)是函數(shù)重載。<返回類型說明符>operator<運算符符號>(<參數(shù)表>){<函數(shù)體>}一般形式例創(chuàng)建對象常見的有下面幾種方式:
myClassob1;//調(diào)用不帶參數(shù)的構(gòu)造函數(shù)myClassob2(ob1);//調(diào)用缺省拷貝構(gòu)造函數(shù)或用戶自定義拷貝構(gòu)造函數(shù)myClassob3(3);//調(diào)用帶整數(shù)類參數(shù)的構(gòu)造函數(shù)myClassob4=ob1;//調(diào)用拷貝構(gòu)造函數(shù)myClassob5;ob5=ob1;//調(diào)用缺省賦值運算符函數(shù)或自定義成員函數(shù)operator=myClassob6=3;//調(diào)用帶整型參數(shù)的構(gòu)造函數(shù)(1)賦值操作是在對象被創(chuàng)建完畢以后的時間段完成的,完成對象狀態(tài)的修改;而初始化針對一個新對象,是在對象創(chuàng)建的階段,完成對其最初狀態(tài)的設(shè)置。(2)運算符重載后,可以按它的表達方式使用,但不能改變它們的優(yōu)先級和要求的操作數(shù)數(shù)目。運算符被重載后,原有意義沒有失去,只是定義了相對于一特定類的一個新運算符。運算符函數(shù)用成員函數(shù)重載時,必須是公有的。12.6運算符重載如果類沒有自定義的重載賦值運算符函數(shù),缺省賦值運算符函數(shù)和缺省拷貝構(gòu)造函數(shù)一樣,“逐域”拷貝對象中的每個數(shù)據(jù)成員,這樣,當類中存在指針數(shù)據(jù)成員時就會存在和拷貝構(gòu)造函數(shù)同樣的弊端。例運算符重載函數(shù)classMessage{public:
…//略Message&operator=(Message&me);
…//略}Message&Message::operator=(Message&me){if(this==&me)return*this;//判斷是否同一個對象delete[]buffer;buffer=newchar[strlen(me.buffer)+1];strcpy(buffer,me.buffer);return*this;}12.7類的特殊成員const可以修飾類的數(shù)據(jù)成員和成員函數(shù),分別稱作const數(shù)據(jù)成員、const成員函數(shù)。#include<iostream.h>classmyClass{private:constintci; //常量數(shù)據(jù)成員int&ref; //引用數(shù)據(jù)成員public:myClass(int&i):ci(10),ref(i)//冒號(:)后面的ci(10),ref(i)就是成員初始化列表{ }voidShow(){cout<<ci<<”,”<<ref<<endl;}};voidmain(){inta=10;myClassob(a);ob.Show();}定義const變量時必須給出初始值,但C++規(guī)定,不允許在類的聲明中為類的常量和引用數(shù)據(jù)成員提供初始值初始化的方式:成員初始化列表12.7.1.1const數(shù)據(jù)成員類名::類名(參數(shù)表):數(shù)據(jù)成員名(值),數(shù)據(jù)成員名(值),…數(shù)據(jù)成員名(值){函數(shù)體}成員初始化列表的一般形式幾點說明:1)成員初始化列表用于在創(chuàng)建對象的同時給對象數(shù)據(jù)成員賦初始值,成員初始化列表只能用在構(gòu)造函數(shù)中。成員初始化列表必須寫在構(gòu)造函數(shù)的參數(shù)表和構(gòu)造函數(shù)的函數(shù)體之間,且與參數(shù)表之間用冒號(:)隔開。2)如果構(gòu)造函數(shù)定義在類的說明之外,成員初始化列表只能寫在構(gòu)造函數(shù)定義處的參數(shù)表和構(gòu)造函數(shù)函數(shù)體之間。3)成員初始化列表的各項應用逗號隔開。成員初始化列表不僅可以給常量和引用數(shù)據(jù)成員初始化,而且可以給普通數(shù)據(jù)成員初始化。const成員函數(shù)12.7.1.2當我們不希望函數(shù)修改類的數(shù)據(jù)成員的值時,可以把該成員函數(shù)指定為const成員函數(shù)classmyClass{private:intvalue;int*ptr;public:…intGet()const//Get函數(shù)不能修改任何數(shù)據(jù)成員{returnvalue;}voidGood(inti)const //Good函數(shù)也不能修改任何數(shù)據(jù)成員{*ptr=i;//修改的是ptr指向的數(shù)據(jù)空間,該空間不是類的數(shù)據(jù)成員}};const應該放在成員函數(shù)參數(shù)表和函數(shù)體之間。如果成員函數(shù)在類的說明體外定義,在類的說明中該成員函數(shù)原型說明后也應加上const幾點說明:1)const對象只能訪問類的const成員函數(shù),不能訪問非const成員函數(shù),對于const對象,程序不能修改它的任何數(shù)據(jù)成員。2)編譯器會自動檢查const成員函數(shù),看它有沒有修改該類的數(shù)據(jù)成員,若修改了,則給出編譯錯誤信息。但const成員函數(shù)可以修改被mutable修飾的數(shù)據(jù)成員12.7.1.2const成員函數(shù)12.7.2靜態(tài)成員
在數(shù)據(jù)成員或成員函數(shù)的前加static修飾符,稱為靜態(tài)數(shù)據(jù)成員和靜態(tài)成員函數(shù)。靜態(tài)成員是屬于整個類的而不是某個對象,不會隨對象的消失而消失。靜態(tài)成員變量只存儲一份,為所有對象共用、共享。intcount=0;classmyClass{private:intvalue;public:myClass(){value=0;count++;}~myClass(){count--;}};例#include<iostream.h>classmyClass{private:intvalue;public:staticintcount;//靜態(tài)數(shù)據(jù)成員myClass(){value=0;count++;}~myClass(){count--;}};myClass不再是一個獨立的類,而是一個依賴于全局變量count的類。靜態(tài)數(shù)據(jù)成員12.7.2.1幾點說明:1)靜態(tài)數(shù)據(jù)成員是類的成員,遵從一般類的成員訪問規(guī)則。2)當沒有創(chuàng)建該類的任何對象時,靜態(tài)數(shù)據(jù)成員仍然存在,在創(chuàng)建對象之前,我們通過類名myClass::count來訪問靜態(tài)數(shù)據(jù)成員。3)由于靜態(tài)數(shù)據(jù)成員不屬于特定的對象,因而不能使用構(gòu)造函數(shù)和析構(gòu)函數(shù)進行初始化和撤銷。4)靜態(tài)數(shù)據(jù)成員必須在全局區(qū)定義,注意在定義時不要加上static。靜態(tài)成員函數(shù)12.7.2.2在類之外能通過myClass::count,訪問count,這不符合類的封裝性,應將count說明為靜態(tài)私有數(shù)據(jù)成員,定義靜態(tài)成員函數(shù)GetCount()僅供類的對象來訪問count,這樣也能保持靜態(tài)成員不依賴于特定對象的存在而存在的本質(zhì)。#include<iostream.h>calssPoint{private:staticintcount;public:…staticintGetCount(){returncount;}};intPoint::count=0;//仍然需要在全局區(qū)定義intmain(){…}例12.7.2.2靜態(tài)成員函數(shù)幾點說明:1)在類的說明中,對靜態(tài)成員函數(shù)的原型,必須要有static,以表示為靜態(tài)成員函數(shù)。靜態(tài)成員函數(shù)也可以在類外定義,在定義時省略static關(guān)鍵字。2)當對象被創(chuàng)建后,也可以通過對象名來訪問靜態(tài)成員函數(shù),但要“顯式”地傳遞對象指針,才能訪問對象的成員(不推薦這種用法)。3)靜態(tài)成員函數(shù)中只能直接訪問類的靜態(tài)數(shù)據(jù)成員,不能直接訪問類的非靜態(tài)數(shù)據(jù)成員。4)由于不傳遞this指針,從本質(zhì)上看,靜態(tài)成員函數(shù)不能算是嚴格的類的成員函數(shù)。靜態(tài)成員函數(shù)可以在沒有聲明類的任何實例(對象)之前就被執(zhí)行。12.8對象成員在類中可以說明具有類類型的數(shù)據(jù)成員,即對象成員#include<iostream.h>#include<string.h>classstudentID{intvalue;public:studentID(intd=0){value=d;cout<<"Assigningstudentid"<<value<<endl;};~studentID(){cout<<"Destructingid"<<value<<endl;};};classstudent{charname[20];studentIDid;public:student(char*pname="noname",intssID=0):id(ssID){cout<<"Constructingstudent"<<pname<<endl;strncpy(name,pname,sizeof(name));};~student{cout<<"Destructingstudent"<<pname<<endl;};};voidmain(){students(“Tom",9818);}程序運行結(jié)果:Assigningstudentid9818ConstructingstudentTomDestructingstudentTomDestructingid981812.8對象成員幾點說明:1)類的構(gòu)造函數(shù)應在其初始化列表里調(diào)用對象成員類的構(gòu)造函數(shù)。也就是說,要想初始化對象成員id,必須在類Student構(gòu)造函數(shù)的成員初始化列表中進行。2)如果有多個對象成員需要初始化,則用逗號隔開各項。對象成員的初始化順序可以隨意安排,但編譯器對對象成員的構(gòu)造函數(shù)的調(diào)用順序取決于對象成員在類中說明的順序,與它們在成員初始化列表中給出的順序無關(guān)。3)析構(gòu)函數(shù)的調(diào)用順序恰好和構(gòu)造函數(shù)的調(diào)用順序相反,具有唯一性。4)創(chuàng)建對象s時,編譯器先執(zhí)行對象成員的構(gòu)造函數(shù)體為對象進行初始化,創(chuàng)建完所有的對象成員之后,才執(zhí)行這個擁有對象成員的對象的構(gòu)造函數(shù)體,以初始化該對象的其他成員。12.9對象數(shù)組與對象指針#include<iostream.h>classmyClass{private:intvalue;public:myClass(){value=0;}myClass(intv){value=v;}voidSet(intv){value=v;}voidShow(){cout<<value<<endl;}};intmain(){myClassarr[3];intii;for(ii=0;ii<3;ii++)arr[ii].Show();cout<<endl;for(ii=0;ii<3;ii++){arr[ii].Set(ii);arr[ii].Show();}return0;}對象數(shù)組程序?qū)⒆詣诱{(diào)用不帶參數(shù)的構(gòu)造函數(shù)myClass()來創(chuàng)建三個數(shù)組元素,對象數(shù)組的初始化1)myClassarr[3]={0,1,2};調(diào)用帶一個整型參數(shù)的構(gòu)造函數(shù)myClass(int)2)myClassarr[3]={myClass(0),myClass(1),myClass(2)};12.9.1對象數(shù)組幾點說明:1)基本類型的數(shù)組不提供初值,系統(tǒng)會給所有元素清0,但對象數(shù)組如果不給初始值,對象元素的數(shù)據(jù)成員不一定清0。系統(tǒng)會調(diào)用不帶參數(shù)的構(gòu)造函數(shù)(可能是缺省的,也可能是用戶自定義的)來創(chuàng)建對象元素。2)建議自定義不帶參數(shù)的構(gòu)造函數(shù)12.9.2對象與指針classmyClass{private:intvalue;public:myClass(intv){value=v;}voidShow(){cout<<value<<endl;}};intmain(){myClassob(10);myClass*ptr=&ob;//ptr指向?qū)ο髈bptr->Show();//利用成員訪問運算符‘->’訪問所指對象的成員函數(shù)myClassarr[3]={0,1,2};ptr=arr;for(intii=0;ii<3;ii++){ptr->Show();ptr++;}return0;}對象指針指向?qū)ο髷?shù)組的指針ptr,如果通過ptr++或ptr--移動來改變指向關(guān)系,并不是指針值簡單的增減1,而是增減一個對象所占的字節(jié)數(shù)。12.9.2對象與指針classmyClass{private:intvalue;public:myClass(intv){value=v;}myClass(){value=0;}};voidmain(){myClass*ptr=NULL;ptr=newmyClass(1);//調(diào)用構(gòu)造函數(shù)myClass(int)創(chuàng)建動態(tài)對象if(ptr==NULL){ cout<<”內(nèi)存不足!”<<endl; exit(1);}myClass*arr=NULL;arr=newmyClass[5];if(arr==NULL){cout<<”內(nèi)存不足!”<<endl; exit(1);}delete[]arr;deleteptr;}動態(tài)對象數(shù)組幾點說明:1)動態(tài)對象數(shù)組與前面通過數(shù)組定義得到的對象數(shù)組的主要區(qū)別是:分配的內(nèi)存空間不在同一個內(nèi)存區(qū),通過定義的對象數(shù)組是分配在棧空間或者全局數(shù)據(jù)區(qū),而動態(tài)對象數(shù)組是在堆空間里分配內(nèi)存;2)不能丟失ptr指針,否則,將無法引用動態(tài)對象數(shù)組,更嚴重的是,將造成所謂的“內(nèi)存泄漏”。3)用new分配動態(tài)對象數(shù)組時,不能指定任何初始值。下面的語句存在語法錯誤:arr=newmyClass[5](1);針對動態(tài)對象數(shù)組,只能調(diào)用不帶參數(shù)的構(gòu)造函數(shù)來創(chuàng)建每一個動態(tài)對象元素。因此,強烈建議在類的設(shè)計中一定要提供自定義的不帶參數(shù)的構(gòu)造函數(shù)。12.9.2對象與指針12.10友元
類具備封裝和信息隱藏的特性,只有類的成員函數(shù)才能訪問類的私有成員。在某些情況下,特別是在對成員函數(shù)多次調(diào)用時,由于參數(shù)傳遞,類型檢查和安全性檢查等都需要時間開銷,而影響程序的運行效率。因此,C++中提出友元的概念,友元能夠擴大私有成員的訪問范圍到全局函數(shù)或其他類的某成員函數(shù),甚至擴大到其他類整個域。友員給予別的類或非成員函數(shù)訪問私有成員的權(quán)利,使用友員目的是基于程序的運行效率。類的友元分為友元函數(shù)和友元類。12.10.1友元函數(shù)
友元函數(shù)是定義在類外部的普通函數(shù),但需要在類內(nèi)進行說明,在說明時前面加以關(guān)鍵字friend。友元函數(shù)不是成員函數(shù),但是它能夠訪問類中的私有成員。friend返回類型函數(shù)名(參數(shù)類型表);類中友元函數(shù)的原型說明classmyClass{private:intvalue;public:friendvoidFriendSet(myClass&ob,intv);};voidFriendSet(myClass&ob,intv)//友元函數(shù)的定義中不能加friend關(guān)鍵字{ob.value=v;}voidmain(){myClassfri;FriendSet(fri,10);}12.10.1友元函數(shù)幾點說明:1)友元函數(shù)與成員函數(shù)的區(qū)別:Set()是類的成員函數(shù),編譯器調(diào)用Set函數(shù)時,會把this指針作為隱含參數(shù)傳遞給它。FriendSet是類的友元函數(shù),不屬于myClass類的成員函數(shù)。編譯器調(diào)用它時,沒有this指針傳遞給它。因此,在友元函數(shù)的參數(shù)中都必須明確、“顯式”地指明要訪問的對象,以表明它究竟訪問的是哪個對象的成員。2)如果在類中說明友元函數(shù)時,給出了該函數(shù)的函數(shù)體代碼,則該友元函數(shù)也是內(nèi)聯(lián)的。3)類的成員函數(shù)可以用作其他類的友元。4)友元函數(shù)可以同時用作多個類的友元。classComplex{private:doublereal,imag;public:Complex(doubler=0,doublei=0);voidprint()const;//復數(shù)運算friendComplexoperator+(constComplex&c1,constComplex&c2);friendComplexoperator-(constComplex&c1,constComplex&c2);friendComplexoperator-(constComplex&c);};
intmain(){Complexc1(2.5,3.7),c2(4.2,6.5);Comp
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 異質(zhì)數(shù)據(jù)融合方法-洞察分析
- 水利工程生態(tài)效益評估-洞察分析
- 《珍愛生命注意安全》課件
- 2024年05月新疆中國郵政儲蓄銀行新疆分行春季社會招考筆試歷年參考題庫附帶答案詳解
- 2025年浙科版七年級歷史下冊階段測試試卷含答案
- 2024年北師大版八年級歷史上冊月考試卷含答案
- 2024年杭州市蕭山區(qū)第一人民醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 2024年05月北京寧波銀行北京分行校園招考實習生筆試歷年參考題庫附帶答案詳解
- 2024年05月北京中信銀行資產(chǎn)托管部社會招考(512)筆試歷年參考題庫附帶答案詳解
- 2025年北師大新版七年級英語下冊階段測試試卷
- ps經(jīng)典課程-海報設(shè)計(第六講)
- 江蘇省泰州市2023-2024學年高一上學期期末語文試題及答案
- 【MOOC】工程制圖解讀-西安交通大學 中國大學慕課MOOC答案
- 期末復習(試題)-2024-2025學年三年級上冊數(shù)學蘇教版
- 內(nèi)鏡中心年終總結(jié)和計劃
- 周五學習制度
- 運維或技術(shù)支持崗位招聘筆試題與參考答案(某大型央企)2024年
- 2022年新高考I卷讀后續(xù)寫David's run公開課課件-高三英語一輪復習
- 《論語》導讀(復旦版)學習通超星期末考試答案章節(jié)答案2024年
- 杰士德在線測評題
- 第18課《我的白鴿》公開課一等獎創(chuàng)新教學設(shè)計
評論
0/150
提交評論