版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
緒論面向?qū)ο蟪绦蛟O(shè)計(jì):通過增加軟件可擴(kuò)充性和可重用性來改善并提高程序員的生產(chǎn)能力,并控制維護(hù)軟件的復(fù)雜性和軟件維護(hù)的開銷OOP:具有結(jié)構(gòu)化程序設(shè)計(jì)的一切優(yōu)點(diǎn)
將數(shù)據(jù)和對數(shù)據(jù)的操作放在一起,作為一個相互依存、不可分割的一個整體,抽象成一種新的數(shù)據(jù)類型—類兩大技術(shù)(兩個重要原理)數(shù)據(jù)抽象信息隱藏OPP支持的軟件開發(fā)策略
編寫可重用代碼編寫可維護(hù)的代碼共享代碼精化已有的代碼
OOP的五大基本概念1.對象(Object):數(shù)據(jù)及可以對這些數(shù)據(jù)施加的操作結(jié)合在一起所構(gòu)成的獨(dú)立實(shí)體的總稱,是計(jì)算的最基礎(chǔ)的構(gòu)造塊成員變量(數(shù)據(jù)):表明對象的狀態(tài)成員方法(操作):表明對象的行為一組成員變量和相關(guān)的方法集合2.類(Class):對一組具有相同數(shù)據(jù)和相同操作的對象的描述(定義),依據(jù)共同的行為將有關(guān)對象進(jìn)行的一種分組類中所有對象共享類中所有共同的特性類是對象的抽象程序中:只有類對象是類的實(shí)例運(yùn)行時:只有對象4.消息(Message):要求某個對象執(zhí)行類中所定義的某個操作的規(guī)格說明
5.方法(Method):對象所能執(zhí)行的操作
它是類中定義的函數(shù),描述對象執(zhí)行操作的算法,即響應(yīng)消息的方法OOP方法學(xué)的四大要點(diǎn)1.認(rèn)為世界由各種對象(object)組成,任何事物都是對象,是某個對象類(class)的實(shí)例(instance)2.把所有對象都劃分成各種對象類,每個對象類都定義了一組方法(method),即允許施加于該類對象上的各種操作OOP的三大核心特征
封裝性(Encapsulation)繼承性(Inheritance)多態(tài)性(Polymorphism)1.封裝性:數(shù)據(jù)和加工處理該數(shù)據(jù)的方法緊密結(jié)合在一起構(gòu)成黑匣子的整體對私有數(shù)據(jù)不能執(zhí)行該對象的成員函數(shù)之外的任何其它函數(shù)2.繼承性:一個類直接繼承其父類的全部描述(數(shù)據(jù)和函數(shù))繼承具有傳遞性:若類C繼承類B,類B繼承類A,則類C繼承類A類實(shí)際上繼承了類等級中在其上層的全部基類(父類)的所有描述繼承方式分類(二)單繼承:一個類只有一個父類時(樹結(jié)構(gòu))多繼承:一個類可有多個父類時(圖結(jié)構(gòu))3.多態(tài)性:在類等級的各層中共享(公用)一個行為(函數(shù))的名字,而類等級中的每個類卻各自按照自己的需要來實(shí)現(xiàn)這個行為一個名字,多種語義相同界面,多種實(shí)現(xiàn)函數(shù)重載表達(dá)了最簡單的多態(tài)性voidf(int,int,char);voidf(char,float);voidf(int,int);voidf(float,float);
參數(shù)數(shù)量、類型、順序不同,函數(shù)體也可以完全不同2.行為共享:(1)實(shí)體(模塊)的外部接口稱為行為(2)行為共享允許多個實(shí)體(模塊)具有相同的接口集(3)行為共享增強(qiáng)系統(tǒng)的靈活性(4)行為共享增強(qiáng)系統(tǒng)的抽象
流流是一個抽象的概念,它指的是數(shù)據(jù)從一個源(source)到一個終點(diǎn)(sink)的流動c++提供四個預(yù)定義的開放流cin:標(biāo)準(zhǔn)輸入,通常指鍵盤,對應(yīng)于c中的stdin,cout:標(biāo)準(zhǔn)輸出,通常指屏幕,對應(yīng)于c中的stdoutcerr:標(biāo)準(zhǔn)錯誤輸出,通常指屏幕,對應(yīng)于c中的stderrclog:cerr的全緩沖版(c中沒有等價的)cerr:無緩沖clog:有緩沖定義或說明一個常數(shù)組可采用如下格式:<類型說明符>const<數(shù)組名>[<大小>]…或者const<類型說明符><數(shù)組名>[<大小>]…intconsta[5]={1,2,3,4,5};常對象是指對象常量,定義格式如下:<類名>const<對象名>或者const<類名><對象名>定義常對象時,同樣要進(jìn)行初始化,并且該對象不能再被更新下面定義了一個指向字符串常量的指針:constchar*ptr2=stringprt1;其中,ptr2是一個指向字符串常量的指針。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。因此,*ptr2="x";是非法的,而:ptr2=stringptr2;是合法的。(1)指向常量的指針:指向的常量不能改變1)constchar*pc=”asdf”;//指向常量的指針pc[3]=’a’;//錯pc=”ghik”;//對2)constchar*step[3]={”left”,”right”,”top”};step[2]=”skip”;//對step[2][1]=’i’;//錯(2)常指針:指針本身不能改變,指向的對象可以改變1)char*constpc=”asdf”;//常指針pc[3]=’a’;//對pc=”ghik”;//錯2)char*conststep[3]={“l(fā)eft”,”right”,”top”};step[2]=”skip”;//錯step[2][1]=’i’;//對(3)指向常量的常指針:指針本身及指向的對象均不能改變constchar*constpc=”asdf”;//指向常量的常指針pc[3]=’a’;//錯pc=”ghik”;//錯注意:(1)const總是修飾緊隨其后的東西(2)指向常量的指針不能賦給一般的指針,一般的指針可以賦給指向常量的指針2.常引用使用const修飾符也可以說明引用,被說明的引用為常引用,該引用所引用的對象不能被更新。其定義格式如下:const<類型說明符>&<引用名>例如:constdouble&v;在實(shí)際應(yīng)用中,常指針和常引用往往用來作函數(shù)的形參,這樣的參數(shù)稱為常參數(shù)。在C++面向?qū)ο蟮某绦蛟O(shè)計(jì)中,指針和引用使用得較多,其中使用const修飾的常指針和常引用用得更多。使用常參數(shù)則表明該函數(shù)不會更新某個參數(shù)所指向或所引用的對象,這樣,在參數(shù)傳遞過程中就不需要執(zhí)行拷貝初始化構(gòu)造函數(shù),這將會改善程序的運(yùn)行效率。#includeconstintN=6;voidprint(constint*p,intn);voidmain(){intarray[N];for(inti=0;icin>>array[i];print(array,N);}voidprint(constint*p,intn){cout<<"{"<<*p;for(inti=1;icout<<","<<*(p+i);cout<<"}"<}常成員函數(shù)使用const關(guān)鍵字進(jìn)行說明的成員函數(shù),稱為常成員函數(shù)。只有常成員函數(shù)才有資格操作常量或常對象,沒有使用const關(guān)鍵字說明的成員函數(shù)不能用來操作常對象。常成員函數(shù)說明格式如下:<類型說明符><函數(shù)名>(<參數(shù)表>)const;其中,const是加在函數(shù)說明后面的類型修飾符,它是函數(shù)類型的一個組成部分,因此,在函數(shù)實(shí)現(xiàn)部分也要帶const關(guān)鍵字。下面舉一例子說明常成員函數(shù)的特征。#includeclassR{public:R(intr1,intr2){R1=r1;R2=r2;}voidprint();voidprint()const;private:intR1,R2;};voidR::print(){cout<}voidR::print()const{cout<}voidmain(){Ra(5,4);a.print();constRb(20,52);b.print();}
該例子的輸出結(jié)果為:5,420;522.Inline內(nèi)聯(lián)函數(shù)
包含在類的說明中的成員函數(shù)稱為內(nèi)部函數(shù)
它告訴編譯器一旦有可能就直接用該函數(shù)的代碼取代對該函數(shù)的調(diào)用,以避免函數(shù)調(diào)用的開銷class類名{成員變量;成員函數(shù);}
即使不是在類說明中定義的函數(shù),也可以說明為內(nèi)部的(加inline)以空間換時間內(nèi)聯(lián)函數(shù)的限制
(1)內(nèi)聯(lián)函數(shù)不能包含任意靜態(tài)數(shù)據(jù)(2)內(nèi)聯(lián)函數(shù)不能使用任何循環(huán)switch,goto語句(3)內(nèi)聯(lián)函數(shù)不能是遞歸的(4)內(nèi)聯(lián)函數(shù)中不能有數(shù)組說明(可放在外面說明)幾個重要概念1.函數(shù)原型intget_word(char*,int,float);
把函數(shù)的函數(shù)名,返回類型及使用的參數(shù)的類型和個數(shù)提前告訴編譯程序1)函數(shù)原型通常放在程序的頂部2)c++需要所有函數(shù)都有原型2.缺省參數(shù)intg(chara,intb,intc=0);
調(diào)用時若未給第三個參數(shù),則缺省為0(1)所有取缺省值的參數(shù)都必須出現(xiàn)在不取缺省值的參數(shù)的右邊(2)缺省值只需在第一次被提及的地方指定3.引用類型數(shù)據(jù)的一種類型(同指針類型很相似)c只能通過傳值傳遞參數(shù),不能通過傳遞引用傳遞參數(shù)c++不僅通過傳值傳遞參數(shù),也可通過傳遞引用傳遞參數(shù)(1)引用的概念
引用是給對象(變量)取一個別名,它引入了對象的一個reference在C中只能使用指針建立別名,不能使用引用建立別名在C++中不僅使用指針建立別名,也可使用引用建立別名
定義引用的關(guān)鍵字是type&,它的含義是“type類型的引用”,此引用與type類型對象或變量的地址相聯(lián)系
例一inti;int&j=i;
創(chuàng)建了一個整型引用變量j,它是i的地址的別名,即j是i的同義詞,它們表示同一個對象例二inti;int&j;錯j=i;定義引用類型變量時就必須初始化而externint&i;//正確,不必給出初值
例三
inti;int&j=i;i=5;j=i+1;i,j的值均為6引用是對象本身,而不是副本,所以對對象或?qū)σ玫娜魏尾僮鞫紩绊懙剿鼈児餐膶ο笠粋€引用可看作一個特殊類型的指針引用與指針的差別(1)引用必須初始化(2)初始化后不能再作為其他對象的別名引用可以使用臨時變量來進(jìn)行初始化(1)用常量初始化引用(引用為—常量的別名)int&ir=1024;intT1=1024;int&ir=T1;(T1為臨時變量)(2)用不同類型的對象初始化引用unsignedintui=20;int&ir=ui;
unsignedintui=20;intT2=int(ui);int&ir=T2;(T2為臨時變量)(2)引用的用途
獨(dú)立引用作為函數(shù)參數(shù)類型作為函數(shù)返回類型1)獨(dú)立引用
a.獨(dú)立引用的限制b.理解int*&p的含義(從右往左理解)2)作為函數(shù)參數(shù)傳遞
比較傳值、傳指針、傳引用inta1(intn){return3*n;main()中調(diào)用語句}intx,i=4;voida2(int*n)x=a1(i);//x=12,i=4{*n=(*n)*3;a2(&i);//i=12}a3(i);//i=36voida3(int&n){n=3*n;}傳值的缺點(diǎn)1、單向傳遞,結(jié)果無法返回2、對于大型對象,實(shí)參對形參的賦值耗時太多
3)作為函數(shù)返回類型
甚至可使返回值作為賦值號左側(cè)的元素,即函數(shù)調(diào)用可以放在賦值語句的左端類的一般形式class類名{private: 私有段數(shù)據(jù)及函數(shù);protected:保護(hù)段數(shù)據(jù)及函數(shù);public:公有段數(shù)據(jù)及函數(shù);};成員變量和成員函數(shù)1.成員變量成員變量的聲明與普通變量的聲明方式相同,但聲明中不允許進(jìn)行初始化賦值
允許不允許classstack classstack {int*lst;{int *lst;intmax_size;intmax_size;intnb_elements;intnb_elements=0;};};一般在聲明時,應(yīng)按成員變量類型的大小,從小至大聲明,這樣利于機(jī)器進(jìn)行對準(zhǔn)操作,從而提高時空利用率(3)在類的內(nèi)部,可以定義其自身的引用或者指針
classstack{int*lst;intmax_size;intnb_elements;};
classstacklinker{stackmystack;stacklinker*right,*left;};2.成員函數(shù)棧的六種操作{建棧、判棧、入棧、出棧、讀棧、毀棧}在類中應(yīng)給出成員函數(shù)的原型classstack{public:voidcreate(int);intempty();voidpush(int);voidpop();inttop();voiderase();};
成員函數(shù)的具體實(shí)現(xiàn)可在類定義體內(nèi)(為內(nèi)聯(lián)函數(shù)),也可在類定義體外(加上inline成為內(nèi)聯(lián)函數(shù),不加inline成為一般函數(shù))stack的完整實(shí)現(xiàn)如下:
#include<iostream.h>#include<string.h>constchar*msg[]={”stackisempty!\n”,”stackisoverflow!\n”};classstack{int*lst;intnb_elements;intmax_size;voiderr_msg(int);public:voidcreate(int);intempty();voidpush(int);voidpop();inttop();voiderase();};viodstack::err_msg(intcode){cout<<msg[code];}voidstack::create(intsize){max_size=size;lst=newint(size);nb_elements=0;}intstack::empty(){return(nb_elements==0);}voidstack::push(intelement){if(nb_elements==max_size)err_msg(1);elselst[++nb_elements]=element;}voidstack::pop(){if(nb_elements==0)err_msg(0); else--nb_elements;}intstack::top(){if(nb_elements==0)err_msg(0);elsereturn(lst[nb_elements]);}voidstack::erase(){deletelst;}main() {stacks;inti;s.create(100);for(i=0;i<=100;++i)s.push(i);for(i=0;i<=100;++i){cout<<s.top()<<’,’;s.pop();}s.erase();結(jié)果:stackisoverflow}99,98,……1,0,stackisempty類類型常量和const成員函數(shù)1.
135為int型常量2.35.7為double型常量’C’’f’為char型常量某些類類型存在常量如:有復(fù)數(shù)類complex,則2+3i為complex類的類型常量
不存在像基本類型常量那樣形式的類類型常量,類類型的常量是以其他方式表達(dá)的2.在程序中對const聲明的常量進(jìn)行賦值是不允許的constcharblank=’’;blank=’\0’;error3.只有通過公有成員函數(shù)才能修改一個類的對象為了確保某個對象是常量,編譯器必須有辦法區(qū)別“安全”及“不安全”的成員函數(shù)conststacks;cout<<s.top()<<’\n’; //安全,不改變ss.push(3); //不安全,常量不可改類的設(shè)計(jì)者通過const來指明哪些成員函數(shù)是安全的classstack{public:inttop()const;}只有被說明為const的成員函數(shù)才能由const常量對象調(diào)用1)在類的說明體之內(nèi)定義的const成員函數(shù)const應(yīng)放在函數(shù)名和函數(shù)體之間2)在類的說明體之外定義的const成員函數(shù)必須在聲明及定義處都使用constclassstackclassstack{inttop()const {inttop()const; //聲明{}………..intstack::top()const//定義}{};…………};若某個函數(shù)修改了類中的某個成員變量,則不允許把它聲明為const型的classexample{int*data_member;public:voidok(inti)const //允許{*data-member=i;}voiderr(int*i)const //不允許{data-member=i;}};const成員函數(shù)也可以重載構(gòu)造函數(shù)的功能:初始化對象析構(gòu)函數(shù)的功能:釋放空間1.構(gòu)造函數(shù):
系統(tǒng)缺省版本:做公共初始化工作用戶提供版本:做用戶初始化工作2.析構(gòu)函數(shù):
系統(tǒng)缺省版本:做公共的善后工作用戶提供版本:做用戶的善后工作
構(gòu)造函數(shù)和析構(gòu)函數(shù)都具有普通成員函數(shù)的許多共同特性,但也有獨(dú)特的特性1.共同點(diǎn)
(1)沒有返回類型 (2)不能被繼承(3)不能取它們的地址
2.不同點(diǎn)
(1)構(gòu)造函數(shù)可以有參數(shù) 析構(gòu)函數(shù)不能有參數(shù) (2)構(gòu)造函數(shù)不能是虛函數(shù)析構(gòu)函數(shù)可以是虛函數(shù)(3)構(gòu)造函數(shù)不能顯式調(diào)用析構(gòu)函數(shù)可以顯式調(diào)用當(dāng)定義對象時系統(tǒng)自動調(diào)用構(gòu)造函數(shù)(先系后用)當(dāng)刪除對象時系統(tǒng)自動調(diào)用析構(gòu)函數(shù)(先用后系)(1)構(gòu)造函數(shù)的名字必須與類名相同(2)構(gòu)造函數(shù)沒有返回值,在聲明和定義構(gòu)造函數(shù)時是不能說明類型的(3)構(gòu)造函數(shù)只能對數(shù)據(jù)成員做初始化,這些數(shù)據(jù)成員一般為私有成員(4)構(gòu)造函數(shù)一般不做賦初值以外的事情(5)構(gòu)造函數(shù)不能顯式地調(diào)用
析構(gòu)函數(shù)類的一個特殊成員函數(shù),函數(shù)名與類名相同,只是在前面加上一個“~”classstringstring::~string(){intlength;{deletecontents;char*contents; }public;string(char*);~string();};(1)一般析構(gòu)函數(shù)由一系列的delete語句組成(2)若使用完全限定名,可顯式調(diào)用析構(gòu)函數(shù)參數(shù)化的構(gòu)造函數(shù)classpoint{intx,y;public:point(int,int);voidoffset(int,int);};point::point(intvx,intvy){x=vx;y=vy;}voidpoint::offset(intax,intay){x=x+ax;y=y+ay;main()}{pointpt(10,20);pt.offset(10,10);}缺省參數(shù)的構(gòu)造函數(shù)例一.classset{intelems[100];intsize;intcard;public:set(inti=16);};set::set(inti){size=i;if(size>100)size=100;if(size<16)size=16;main()}{sets1(64),s2(16),s3(8),s4;}size取值64161616例二.classpoint{intx,y;public:point(intvx=0;intvy=0){x=vx;y=vy;}};main(){pointp1; //不傳遞參數(shù)x=0,y=0pointp2(10); //只傳遞一個參數(shù)x=10,y=0pointp3(10,20);//傳遞兩個參數(shù)x=10,y=20}重載構(gòu)造函數(shù)
classx{public:x();x(int);x(int,char);x(float,char);};voidf(){xa,b(1),c(1,’c’),d(2.3,’d’);}注意二義性classx{public:x();x(inti=0);};main(){xa(10);//正確xb;//錯誤}拷貝構(gòu)造函數(shù)
一種特殊的構(gòu)造函數(shù)(1)為一個構(gòu)造函數(shù),當(dāng)創(chuàng)建一個新對象時系統(tǒng)自動調(diào)用它(2)它將參數(shù)代表的對象逐域拷貝到新創(chuàng)建的對象中
拷貝構(gòu)造函數(shù)是將自己所在的類的引用作為構(gòu)造函數(shù)的參數(shù)拷貝構(gòu)造函數(shù)的定義的兩種形式1.系統(tǒng)產(chǎn)生2.用戶定義1.系統(tǒng)產(chǎn)生#include<iostream.h>classpoint{intx,y;public:point(intvx,intvy){x=vx;y=vy;}voidprint(){cout<<x<<””<<y<<”\n”;}};main(){pointp1(10,20),p2(p1);結(jié)果:1020p1.print();p2.print();1020}2.用戶定義#include<iostream.h>classpoint{intx,y;public:point(intvx,intvy){x=vx;y=vy;}point(constpoint&p){x=p.x;y=p.y;}voidprint(){cout<<x<<””<<y<<”\n”;}};main(){pointp1(10,20),p2(p1);結(jié)果:1020p1.print();p2.print();1020}也可采用賦值形式調(diào)用拷貝構(gòu)造函數(shù)main()main(){pointp1(10,20);{pointp1(10,20);pointp2(p1);pointp2=p1;}}第三節(jié)this指針C++為成員函數(shù)提供了一個稱為this的指針,this在所有成員函數(shù)調(diào)用里作為一個隱含參數(shù)傳給成員函數(shù)classpoint{intx,y;public:point(intvx,intvy,point*constthis)//完整{this->x=vx;this->y=vy;}point(intvx,intvy)//半省{this->x=vx;this->y=vy;}point(intvx,intvy){x=vx;y=vy;}//全省};1.每個對象的成員函數(shù)都擁有一個隱含的指針this(靜態(tài)函數(shù)除外)intget_length(){returnlength;}二者等價intget_length(){returnthis->length;}2.this指針是一個常指針,可表示為:x*constthis(可指向常量)3.this指針不能被修改和賦值4.const成員函數(shù)不能修改this所指的對象的成員第四節(jié)
靜態(tài)成員一、靜態(tài)成員變量(1)某個類的所有對象要共同訪問同一個變元,這個變元可能是一個條件標(biāo)志或一個計(jì)數(shù)器(2)為了減少數(shù)據(jù)冗余,防止不一致性,要求一個類的所有對象共享同一個數(shù)據(jù)(3)為了節(jié)約空間開銷,也要求對象共享同一個數(shù)據(jù)處理方法:使用全局變量缺點(diǎn):(1)破壞了信息隱藏原則(2)過多的全局變量會產(chǎn)生重名沖突
為了既達(dá)到與全局變量一樣的效果,又能滿足信息隱藏的原則,提出了靜態(tài)成員變量的概念
特點(diǎn)
若類中某個成員變量被說明成靜態(tài)的,則類的所有對象共享這個成員變量靜態(tài)成員變量不屬于某個對象,而屬于整個類classABCD{charch;staticints;};ABCDa,b,c,d;
為了把某個成員變量說明為靜態(tài)的,只須在原有說明前加上static靜態(tài)成員變量可以是public、private和protected段的#include<iostream.h>#include<stdlib.h>classcounter{staticintcount;intobjnumber;public:counter(){count++;obinumber=count;}voidshow(){cout<<”obj”<<objnumber<<””cout<<”count=”<<count<<”\n”;}};intcounter::count=0;main(){counterobj1,obj2,obj3,obj4;obj1.show();cout<<”--------------------\n”;obj1.show();obj2.show();cout<<”--------------------\n”;obj1.show();obj2.show();obj3.show();cout<<”--------------------\n”;obj1.show();obj2.show();obj3.show();obj4.show();}輸出結(jié)果:obj1 count=4----------------obj1 count=4obj2 count=4----------------obj1 count=4obj2 count=4obj3 count=4----------------obj1 count=4obj2 count=4obj3 count=4obj4 count=4靜態(tài)成員函數(shù)static函數(shù)1.是一個成員函數(shù),使用時要用“類名::”作為它的限定詞2.是一個特殊的成員函數(shù),它不屬于某一個特定的對象而只屬于一個類,不能象一般的成員函數(shù)那樣隨意地訪問對象中的非靜態(tài)的數(shù)據(jù)內(nèi)容3.沒有this指針4.要訪問非靜態(tài)成員,必須要有限定詞#include<iostream.h>#include<string.h>classstring{staticinttotal_length;intlength;char*contents;public:string(char&s){length=strlen(s);contents=newchar[length+1];strcpy(contents,s);}staticintset_total_length(){total_length=total_length+length;//errorreturntotal_length;}~string(){delete[]contents;}};intstring::total_length=0;main(){stringobj1(“Thefirstobject”);cout<<string::set_total_length()<<”\n”;stringobj2(“Thesecondobject”);cout<<string::set_total_length()<<”\n”;}
要想讓靜態(tài)成員函數(shù)識別對象,只能靠參數(shù)傳遞的方式實(shí)現(xiàn)staticintset_total_length(stringobj){total_length=total_length+obj.length;returntotal_length;}main(){stringobj1(“Thefirstobject”);cout<<string::set_total_length(obj1)<<”\n”;stringobj2(“Thesecondobject”);cout<<string::set_total_length(obj2)<<”\n”;}在被調(diào)用靜態(tài)成員函數(shù)前,必須綴上類名第五節(jié)
友元一、友元的概念(1)封裝性和信息隱藏使對象和外界以一堵不透明的墻隔開,友元在這堵墻上開了一個小孔(2)友元是以犧牲信息隱藏原則,削弱封裝性來提高編程效率,增大了類與類之間的藕合度只要將外界的某個對象說明為某一個類的友元,則它可以訪問這個類中的所有成員
友元的種類1.一般函數(shù)2.另一個類的成員函數(shù)3.另一個類二、友元的聲明和定義
將friend放在函數(shù)名或類名的前面,此聲明可放在任何段中特別注意友元不屬于任何類三、友元函數(shù)作為友元的函數(shù)classx{inti;friendvoidfunc(x*,int);//友元函數(shù)public:voidmember_func(int); //成員函數(shù)};voidfunc(x*xp,inta){xp→i=a;}//無需作用域voidx::member_func(inta){i=a;}//必須作用域成員函數(shù)可以在類中實(shí)現(xiàn),也可以類外實(shí)現(xiàn)友元函數(shù)可以在類中實(shí)現(xiàn),也可以類外實(shí)現(xiàn)在類外實(shí)現(xiàn)時,成員函數(shù)必須用作用域區(qū)分符(::)限定它屬于哪一個類在類外實(shí)現(xiàn)時,友元函數(shù)不須用作用域區(qū)分符(::)限定它屬于哪一個類友元函數(shù)沒有this指針,不能確定是訪問哪個對象的私有數(shù)據(jù),故必須在參數(shù)表中顯式地指明要訪問的對象友元成員函數(shù)作為友元的另一個類中的成員函數(shù)classx{public:voidmember_func();};classy{inti;
friendvoidx::member_func();};友元類作為友元的另一個類
classx{inti,j;public:voidmember_func1();voidmember_func2();voidmember_func3();};classy{inti,j;friendx;};運(yùn)算符重載
不能改變優(yōu)先級不能改變操作數(shù)的個數(shù)不能重載沒有的符號(自己發(fā)明)單目可以重載雙目可以重載三目不能重載運(yùn)算符重載的能力增強(qiáng)了C++語言的可擴(kuò)充性new可以重載delete可以重載
在C++中,運(yùn)算符的重載,實(shí)際上是一種函數(shù)調(diào)用的形式
用成員函數(shù)重載運(yùn)算符用友元函數(shù)重載運(yùn)算符+可以定義為減運(yùn)算*可以定義為除運(yùn)算
顛倒黑白重載方式的選擇
(1)若運(yùn)算符的操作要修改對象的狀態(tài),或需要左值運(yùn)算數(shù)(如=,*=,++),選擇成員函數(shù)(2)若運(yùn)算符的操作數(shù)(特別是第一個操作數(shù))希望有隱藏類型轉(zhuǎn)換,必須選擇友元函數(shù)既要聲明、也要定義
用成員函數(shù)重載運(yùn)算符重載運(yùn)算符的成員函數(shù)稱為運(yùn)算符重載函數(shù),有this指針,是一種特殊的成員函數(shù)1.聲明格式classclass_name{typeoperator@(arg-list);}2.定義格式typeclass_name::operator@(arg-list){……}其中:type為返回類型,@為要重載的運(yùn)算符operator為關(guān)鍵字,arg-list為該運(yùn)算所需要的操作數(shù)若@為一元的,則arg-list為空,當(dāng)前對象作為單操作數(shù)若@為二元的,則arg-list中有一個操作數(shù),當(dāng)前對象為@的左操作數(shù),arg-list中的操作數(shù)為@的右操作數(shù)
隱式調(diào)用顯式調(diào)用一元
aa@或@aaaa.operator@()
無參數(shù),隱式傳遞
隱式調(diào)用顯式調(diào)用二元
aa@bbaa.operator@(bb)
一個參數(shù),一隱一顯例1classx{intoperator+(x);};intx::operator+(xa){……}main(){xa1,b1;ya2,b2;a1=a1+b1;//正確a2=a2+b2;//錯誤}類x對+已進(jìn)行重載類y對+未進(jìn)行重載例2classpoint{intx,y;public:point(intvx,intvy){x=vx;y=vy;}point(){x=0;y=0;}pointoperator+(pointp);pointoperator-(pointp);voidprint(){cout<<x<<””<<y<<”\n”;}};pointpoint::operator+(pointp){pointpp;pp.x=x+p.x;pp.y=y+p.y;returnpp;}pointpoint::operator-(pointp){pointpp;pp.x=x-p.x;pp.y=y-p.y;returnpp;}main(){pointp1(10,10);p2(20,20);p1=p1+p2;p1.print();}
運(yùn)算結(jié)果:3030用友元函數(shù)重載運(yùn)算符重載運(yùn)算符的友元函數(shù)也稱為運(yùn)算符重載函數(shù)1.聲明格式classclass_name{friendtypeoperator@(arg-list);}2.定義格式typeoperator@(arg-list){……}若@為一元的,則arg-list中有一個操作數(shù),作為唯一的操作數(shù)若@為二元的,則arg-list中有二個操作數(shù),作為運(yùn)算的兩個操作數(shù)隱式調(diào)用顯式調(diào)用一元aa@或@aaoperator@(aa)
一個參數(shù),顯式傳遞隱式調(diào)用顯式調(diào)用二元aa@bboperator@(aa,bb)
二個參數(shù),顯式傳遞例1
classpoint{intx,y;public:point(intvx,intvy){x=vx;y=vy;}point(){x=0;y=0;}friondpointoperator+(pointp1;pointp2);friondpointoperator-(pointp1;pointp2);voidpoint(){cout<<x<<””<<y<<”\n”;}};pointoperator+(pointp1;pointp2);{pointp;p.x=p1.x+p2.x;p.y=p1.y+p2.y;returnp;}pointoperator-(pointp1;pointp2);{pointp;p.x=p1.x-p2.x;p.y=p1.y-p2.y;returnp;}main(){pointp1(10,10);p2(20,20);p1=p1+p2;p1.print();}
運(yùn)算結(jié)果:3030注意1.為什么要用友元函數(shù)重載運(yùn)算符2.=,(),[],→只能用成員函數(shù)重載3.<<,>>只能用友元函數(shù)重載4.友元函數(shù)重載單目運(yùn)算符時要特別小心若單目運(yùn)算符要改變對象的狀態(tài),且用友元函數(shù)重載該運(yùn)算符,則應(yīng)使用引用參數(shù)
三、幾個特殊運(yùn)算符的重載1.++和--前綴方式++i,--i后綴方式i++,i--(1)前綴方式
aa.operator++()成員函數(shù)重載operator++(X&aa)友元函數(shù)重載aa.operator--()成員函數(shù)重載operator--(X&aa)友元函數(shù)重載(2)后綴方式
aa.operator++(int)成員函數(shù)重載operator++(X&aa,int)友元函數(shù)重載aa.operator--(int)成員函數(shù)重載operator--(X&aa,int)友元函數(shù)重載
隱式調(diào)用a++但a++3;//error顯式調(diào)用a.operator++(0)a.operator++(3);//ok=賦值運(yùn)算符
不能被友元函數(shù)重載,不能被繼承自動重載:系統(tǒng)定義人工重載:用戶定義缺省拷貝構(gòu)造函數(shù):新建一個對象,再拷貝缺省賦值運(yùn)算符重載函數(shù):只拷貝(目的對象已存在)例
Aa; Ab=a; (調(diào)用缺省拷貝構(gòu)造函數(shù)) Aa,b; b=a; (調(diào)用缺省賦值運(yùn)算符重載載函數(shù))缺省的成員函數(shù)重載賦值運(yùn)算符X& X::operator=(constX&source){//按成員逐域復(fù)制}例1classstring{char*ptr;intlength;string&operator=(string&str);string(string&str);};string&string::operator=(string&str){if(length==0)deleteptr;ptr=newchar[str.length+1];strcpy(ptr,str.ptr);length=str.length;}現(xiàn)在可以使用:str1=str2例2指針懸掛問題classstring僅有缺省賦值運(yùn)算符有時是不夠的{char*contents;intsize;public:string(intsz){contents=newchar[sz];}~string(){deletecontents;}};沒有重載賦值運(yùn)算符main(){strings1(10),s2(20);s1=s2;//調(diào)用缺省賦值運(yùn)算符}缺省賦值運(yùn)算符的功能:逐域賦值(1)s2的contents->s1的contents(2)s2的size->s1的size解決方法:重載賦值運(yùn)算符使其不僅能賦值成員contents,size,也要復(fù)制非成員(具體內(nèi)容)加上:voidoperator=(string*);voidstring::operator=(string*str){if(this==str)return;deletecontents;contents=newchar[size=str→size];strcpy(contents,str→contents);}解決了指針懸掛問題3.()和[]函數(shù)調(diào)用運(yùn)算符和下標(biāo)運(yùn)算符例1
classstring{char*ptr;public:string(constchar*);char&operator[](int);};char&string::operator[](inti){returnptr[i];}stringss=”asdf”;ss[1]=ss[3];相當(dāng)于ss.operator[](1)=ss.operator[](3);ssS的新值為”afdf”
new和delete的重載(1)new和delete是運(yùn)算符,可以重載(2)申請空間可以是基本內(nèi)存,擴(kuò)充內(nèi)存、擴(kuò)展內(nèi)存、硬盤重載類型局部重載:在某一個類中進(jìn)行,用成員函數(shù)重載運(yùn)算符函數(shù)全局重載:在任何類外進(jìn)行,用普通函數(shù)重載運(yùn)算符函數(shù)
new可重載malloc()不可重載deletefree()void*operatornew(size-tsize,……){//完成分配工作returnpointer-to-memory;}voidoperatordelete(void*p,……){//釋放由P指向的存貯空間}(1)對operatornew()來說,它的第一個參數(shù)必須是size-t類型,這是一個在標(biāo)準(zhǔn)頭文件<stddef.h>中定義的與實(shí)現(xiàn)有關(guān)的整型類型,必須返回void*類型(2)對operatordelete來說,它的第一個參數(shù)必須是void*類型,第二個參數(shù)的類型是size-t(可選,刪除對象的大小),必須返回void類型局部重載(1)類x的x::operatornew()類x的x::operatordelete()它們不是針對x類的對象操作的是靜態(tài)成員函數(shù)(無論是否有static)(2)new在構(gòu)造函數(shù)之前調(diào)用,分配構(gòu)造函數(shù)建立X類對象的內(nèi)存delete在析構(gòu)函數(shù)之后調(diào)用,釋放析構(gòu)函數(shù)剛剛破壞的X類對象的內(nèi)存(3)一個類只能聲明一個operatordelete(),故operatordelete()不能進(jìn)行函數(shù)重載一個類可以聲明多個operatornew(),故operatornew()可以進(jìn)行函數(shù)重載(4)重載的new()和delete()是可以繼承的類型轉(zhuǎn)換
一般類型轉(zhuǎn)換隱式類型轉(zhuǎn)換(標(biāo)準(zhǔn)類型轉(zhuǎn)換)顯式類型轉(zhuǎn)換強(qiáng)制轉(zhuǎn)換法函數(shù)轉(zhuǎn)換法
強(qiáng)制法函數(shù)法inti,j;inti,j;cout<<(float)(i+j);cout<<(float(i+j)類類型轉(zhuǎn)換構(gòu)造函數(shù)轉(zhuǎn)換函數(shù)標(biāo)準(zhǔn)類型標(biāo)準(zhǔn)類型:標(biāo)準(zhǔn)類型轉(zhuǎn)換標(biāo)準(zhǔn)類型類類型:構(gòu)造函數(shù)類類型標(biāo)準(zhǔn)類型:類型轉(zhuǎn)換函數(shù)類類型類類型:類型轉(zhuǎn)換函數(shù)一、構(gòu)造函數(shù)
不能將類類型轉(zhuǎn)換為類類型只能將標(biāo)準(zhǔn)類型轉(zhuǎn)換為類類型不能將類類型轉(zhuǎn)換為標(biāo)準(zhǔn)類型
條件:此類一定要有一個只帶一個參數(shù)的構(gòu)造函數(shù)二、轉(zhuǎn)換函數(shù)特殊的成員函數(shù)(不能為友元函數(shù)),可以被繼承、可以是虛函數(shù)、不能重載(函數(shù)重載),無參數(shù),無返回類型,必須有返回函數(shù),返回具有type類型的對象。X::operatorY(){Yy;……returny;}功能:X類類型標(biāo)準(zhǔn)類型X類類型Y類類型隱式使用:inti=a;顯式使用:inti=a.operatorint();
一般使用隱式方式,僅當(dāng)需要明確指出所使用的是哪一個轉(zhuǎn)換函數(shù)時才使用顯式方式
二義性問題若X類有X(int)構(gòu)造函數(shù)operatorint()轉(zhuǎn)換函數(shù)則inti=a;隱式調(diào)用轉(zhuǎn)換函數(shù)Xa=i;隱式調(diào)用構(gòu)造函數(shù)則語句a=a+i將會產(chǎn)生二義性,此時必須顯式調(diào)用轉(zhuǎn)換函數(shù)
用戶定義的轉(zhuǎn)換函數(shù)只有在無二義性時才能隱式使用解決方法(1)Xb=i; (2)a=a+X(i);a=a+b;說明:(1)編譯程序先按用戶定義的意思,再按標(biāo)準(zhǔn)格式,都不行,則失敗(2)有二義性時,必須使用顯式類型轉(zhuǎn)換
(type)obi或type(obi)派生類提高軟件的可重用性減少工作量避免編寫重復(fù)代碼減少出錯機(jī)會繼承是對象類間的一種相關(guān)關(guān)系,即派生關(guān)系,并具有以下性質(zhì):
類間的共享特性類間的細(xì)微區(qū)別類間的層次結(jié)構(gòu)分類樹反映了派生關(guān)系:最高層是最普遍最一般的,越往下反映的事物越具體,并且下層都包含了上層的特征派生類的概念
引入繼承的目的在于為代碼重用提供有效手段。一方面使用繼承可以重用先前項(xiàng)目的代碼,若原來的代碼不能完全滿足要求,還可以作少量的修改,滿足不斷變化的具體應(yīng)用要求,從而提高程序設(shè)計(jì)的靈活性,避免不必要的重復(fù)設(shè)計(jì)單繼承單繼承:每個類可有多個派生類,但最多只有一個基類,從而形成一棵樹結(jié)構(gòu)多繼承:每個類可有多個派生類,也可有多個基類,從而形成網(wǎng)狀結(jié)構(gòu)一、定義格式:class派生類名:繼承方式基類名{<member-list>};其中:1.class關(guān)鍵字2.:將派生類與基類分開3.繼承方式:publicprotectedprivate缺省:對于類等價于private對于結(jié)構(gòu)等價于public四種繼承方式1.公有派生class派生類名:public基類名{<member-list>};基類所有公有段成員成為派生類公有段成員基類所有保護(hù)段成員成為派生類保護(hù)段成員基類所有私有段成員不能被繼承
即派生類的對象及其成員函數(shù)可直接訪問基類的公有成員和保護(hù)成員2.私有派生class派生類名:private基類名{<member-list>};基類所有公有段成員成為派生類私有段成員基類所有保護(hù)段成員成為派生類私有段成員基類所有私有段成員不能被繼承即派生類的成員函數(shù)可直接訪問基類的公有成員和保護(hù)成員3.保護(hù)派生:class派生類名:protected基類名{<member-list>};基類所有公有段成員成為派生類保護(hù)段成員基類所有保護(hù)段成員成為派生類保護(hù)段成員基類所有私有段成員不能被繼承
即派生類的成員函數(shù)可直接訪問基類的公有成員和保護(hù)成員,還可往下繼承4.部分公開(訪問聲明):為了使基類中的公有和保護(hù)成員在派生類中部分成為公有或保護(hù)成員,部分成為私有成員,可采用:基類名::成員名基類公有成員等價于派生類公有成員基類保護(hù)成員等價于派生類保護(hù)成員注意(1)并未引進(jìn)新成員(2)在調(diào)整名字的訪問時不能說明類型三、成員訪問控制基類性質(zhì)繼承性質(zhì)派生類性質(zhì)
publicpublicpublicprotectedpublicprotectedprivatepublic不能訪問publicprotectedprotectedprotectedprotectedprotectedprivateprotected不能訪問publicprivateprivateprotectedprivateprivateprivateprivate不能訪問
基類與派生類的關(guān)系 任何一個類都可以派生出一個新類,派生類也可以再派生出新類,因此,基類和派生類是相對而言的。一個基類可以是另一個基類的派生類,這樣便形成了復(fù)雜的繼承結(jié)構(gòu),出現(xiàn)了類的層次。一個基類派生出一個派生類,它又做另一個派生類的基類,則原來的基類為該派生類的間接基類。
1.派生類是基類的具體化。 2.派生類是基類定義的延續(xù)。 3.派生類是基類的組合。 派生類將其本身與基類區(qū)別開來的方法是添加數(shù)據(jù)成員和成員函數(shù)。因此,繼承的機(jī)制將使得在創(chuàng)建新類時,只需說明新類與已有類的區(qū)別,從而大量原有的程序代碼都可以復(fù)用。如:classA{
public:
voidf();};classB{
public:
voidf();
voidg();};classC:publicA,publicB{
public:
voidg();
voidh();};Cobj;則對函數(shù)f()的訪問是二義的:obj.f();//無法確定訪問A中或是B中的f()
賦值兼容規(guī)則 賦值兼容規(guī)則是指:在公有派生的情況下,一個派生類的對象可用于基類對象適用的地方。賦值兼容規(guī)則有三種情況(假定類derived由類base派生): (1)派生類的對象可以賦值給基類的對象。 derivedd; baseb; b=d; (2)派生類的對象可以初始化基類的引用。 derivedd; base&br=d;
(3)派生類的對象的地址可以賦給指向基類的指針。 derivedd; base*pb=&d; 多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特征之一。所謂多態(tài)性是指當(dāng)不同的對象收到相同的消息時,產(chǎn)生不同的動作。C++的多態(tài)性具體體現(xiàn)在運(yùn)行和編譯兩個方面,在程序運(yùn)行時的多態(tài)性通過繼承和虛函數(shù)來體現(xiàn),而在程序編譯時多態(tài)性體現(xiàn)在函數(shù)和運(yùn)算符的重載上。
運(yùn)算符重載的實(shí)現(xiàn) 運(yùn)算符的重載形式有兩種:重載為類的成員函數(shù)和重載為類的友元函數(shù)。 運(yùn)算符重載為類的成員函數(shù)的語法形式如下:<函數(shù)類型>operator<運(yùn)算符>(<形參表>){<函數(shù)體>;}
friend<函數(shù)類型>operator<運(yùn)算符>(<形參表>){
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 安裝工程授權(quán)委托書格式樣本3篇
- 搬運(yùn)裝卸合同3篇
- 安徽離婚協(xié)議書新版本3篇
- 房屋買賣合同法律條例3篇
- 文藝演出服裝道具租賃合同3篇
- 工業(yè)試驗(yàn)設(shè)備安裝工程合同書3篇
- 房屋買賣建筑工程保險合同3篇
- 體育場館建設(shè)土石方工程施工合同
- 鐵路維修機(jī)械臺班施工合同
- 創(chuàng)意園區(qū)物業(yè)客服人員聘用合同
- 《中國傳統(tǒng)文化》課件模板(六套)
- 色卡-CBCC中國建筑標(biāo)準(zhǔn)色卡(千色卡1026色)
- 2024-2030年中國水產(chǎn)養(yǎng)殖行業(yè)發(fā)展形勢及投資風(fēng)險分析報(bào)告
- 建筑工程施工現(xiàn)場消防安全培訓(xùn)
- 泵站工程設(shè)計(jì)(共138張課件)
- 汽車保險與理賠課件 7.1認(rèn)識新能源汽車
- 中醫(yī)基礎(chǔ)理論-精氣學(xué)說
- 信息素養(yǎng):效率提升與終身學(xué)習(xí)的新引擎學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 浪潮銷售在線測評題
- 玻璃幕墻工程技術(shù)規(guī)范 JGJ102-2003知識培訓(xùn)
- 天津市河西區(qū)2024-2025學(xué)年數(shù)學(xué)四上期末考試模擬試題含解析
評論
0/150
提交評論