C++面向?qū)ο蟪绦蛟O(shè)計課件_第1頁
C++面向?qū)ο蟪绦蛟O(shè)計課件_第2頁
C++面向?qū)ο蟪绦蛟O(shè)計課件_第3頁
C++面向?qū)ο蟪绦蛟O(shè)計課件_第4頁
C++面向?qū)ο蟪绦蛟O(shè)計課件_第5頁
已閱讀5頁,還剩19頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

C++面向?qū)ο蟪绦蛟O(shè)計-2015級陳偉軟件工程教研室吉林大學(xué)email:***;***2015-2016-2學(xué)期1虛函數(shù)2虛擬表3虛機制的作用4虛函數(shù)的訪問5純虛函數(shù)和抽象類內(nèi)容虛機制的引入classShape{public:

voidShow()const{

cout<<“面積是:”<<Area()<<endl;

}floatArea()const{return0;}};classRectangle:publicShape{public:

Rectangle(floatw,floath){

mWidth=w;mHeight=h;

}

floatArea()const{

returnmWidth*mHeight;

}

private:

floatmWidth,mHeight;};classCircle:publicShape{public:

Circle(floatr):mRadius(r){}

floatArea()const{

returnmRadius*mRadius*3.14;

}

private:

floatmRadius;};main(){

Rectangelrect(1,2);

Circlecir(1);

Shape&sp1=rect;Shape&sp2=cir;sp1.Show();//輸出是0,為什么?

sp2.Show();//輸出是0,為什么?

}靜態(tài)編聯(lián)與動態(tài)編聯(lián)靜態(tài)編聯(lián)(早綁定,靜態(tài)綁定):編譯期間就決定了程序運行時將具體調(diào)用哪個函數(shù)體。即使沒有主程序,也能知道程序中各個函數(shù)體之間的調(diào)用關(guān)系。例上頁:Shape&sp1=rect;

sp1.Show();動態(tài)編聯(lián)(晚綁定,動態(tài)綁定):在運行期間,決定具體調(diào)用哪個函數(shù)體。動態(tài)編聯(lián)的實現(xiàn)多種方式虛機制(使用虛擬函數(shù)和虛擬函數(shù)表)使用虛函數(shù)(例)classShape{public:

virtual~Shape(){}

voidShow()const{

cout<<“面積是:”<<Area()<<endl;

}

virtualfloatArea()const{return0;}};classRectangle:publicShape{public:

Rectangle(floatw,floath){

mWidth=w;mHeight=h;

}

virtualfloatArea()const{

returnmWidth*mHeight;

}

private:

floatmWidth,mHeight;};classCircle:publicShape{public:

Circle(floatr):mRadius(r){}

virtualfloatArea()const{

returnmRadius*mRadius*3.14;

}

private:

floatmRadius;};main(){

Rectangelrect(1,2);

Circlecir(1);

Shape&sp1=rect;Shape&sp2=cir;sp1.Show();//正確輸出2

sp2.Show();//正確輸出3.14

}虛函數(shù)的聲明和定義虛函數(shù)的格式(必須是非靜態(tài)成員函數(shù))聲明:virtual

返回類型

函數(shù)名(參數(shù)列表)[const];定義:同一般成員函數(shù)虛函數(shù)說明:必須是成員函數(shù)靜態(tài)成員函數(shù)和構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)不能是虛的析構(gòu)函數(shù)可以是虛的若類中有其它虛函數(shù),那么析構(gòu)函數(shù)也應(yīng)該是虛的賦值函數(shù)通常不定義為虛的虛函數(shù)可以帶const修飾,也可以不帶訪問控制可以任意

(public、protected、private)派生類中的虛函數(shù)通常采用public繼承方式繼承自基類的虛函數(shù)(除虛的析構(gòu)函數(shù))若基類的析構(gòu)函數(shù)是虛的,那么派生類中的析構(gòu)函數(shù)也是虛的派生類中新的虛函數(shù)派生類override基類中的虛函數(shù)(也稱復(fù)寫、重寫)函數(shù)名字同基類中虛函數(shù)的名字virtual關(guān)鍵字可省略返回類型必須與基類中虛函數(shù)的返回類型相同或相容可能會隱藏基類基類中重載的虛函數(shù)(overwrite,hide)classParent{

public:

virtual~Parent();

virtulalvoidF();

intNormal();

protected:

virtual

Parent*G();

};classChild:publicParent{

public:

virtual~Child(){}

virtulalvoidF();

protected:

virtual

Child*G();

};子類中的虛函數(shù)(例)classParent{

public:

Parent();

virtual~Parent(){}

voidF();

virtualvoidG();

protected:

virtualvoidK();

};classChild:publicParent{

public:

Child();

virtual~Child(){}

voidOther();

virtualvoidG();

protected:

virtualvoidH();

};Parent類的3個虛函數(shù):1.Parent::~Parent()

2.Parent::G()

4.Parent::K()Child類的4個虛函數(shù):1.Child::~Child()

2.Child::G()//Child中Override基類的G()

3.Parent::K()//繼承自父類的K()

4.Child::H()//子類中新定義的H()虛函數(shù)表(例)Parent類的3個虛函數(shù):1.Parent::~Parent()

2.Parent::G()

4.Parent::K()Child類的4個虛函數(shù):1.Child::~Child()

2.Child::G()//Child中Override基類的G()

3.Parent::K()//繼承自父類的K()

4.Child::H()//子類中新定義的H()&Parent::~Parent()&Parent::G()&Parent::K()Parent類的虛函數(shù)表&Child::~Child()&Child::G()&Parent::K()Child類的虛函數(shù)表&Child::H()虛函數(shù)表(虛擬表、虛表、VTable)虛函數(shù)表:一個指針數(shù)組,各元素存放對應(yīng)虛函數(shù)的入口地址說明:要求對應(yīng)的類中至少有一個虛函數(shù)一個類至多有一個虛擬表,同一個類的不同對象共享該虛擬表首次創(chuàng)建該類實例對象時,在內(nèi)存中同時創(chuàng)建該類的虛擬表按照函數(shù)順序的序號依次存放入口地址vptr與虛擬表(例)classShape{public:

virtual~Shape(){}

voidShow()const{

cout<<“面積是:”<<Area()<<endl;

}

virtualfloatArea()const{return0;}};classCircle:publicShape{public:

Circle(floatr):mRadius(r){}

virtualfloatArea()const{

returnmRadius*mRadius*3.14;

}

private:

floatmRadius;};main(){

Rectanglerect(1,2);

Shape&rRect=rect;Shape*pCircle=newCircle(3);

rRect.Show();//正確輸出2

pCircle->Show();//正確輸出9.42

deletepCircle;

}classRectangle:publicShape{public:

Rectangle(floatw,floath){

mWidth=w;mHeight=h;

}

virtualfloatArea()const{

returnmWidth*mHeight;

}

private:

floatmWidth,mHeight;};vptr與虛擬表12vptrrect&Rectangle::Area()3vptr&Circle::Area()rRectpCircle&Rectangle::~Rectangle()&Circle::~Circle()棧區(qū)main(){

Rectanglerect(1,2);

Shape&rRect=rect;Shape*pCircle=newCircle(3);

rRect.Show();

//正確輸出2

pCircle->Show();

//正確輸出9.42

deletepCircle;

}堆區(qū)程序區(qū)//Circle::~Circle()的執(zhí)行代碼

......//Circle::Area()的執(zhí)行代碼.....虛函數(shù)的作用機制---變量的靜態(tài)類型和動態(tài)類型靜態(tài)類型:在編譯期間,可以確定的變量類型

如:Childchild;指針型:Parent*pObj=&child;引用型:Parent&obj=child;對象型:Parentobj=child;//對象型中obj的靜態(tài)、動態(tài)一致動態(tài)類型:在運行時,才可以確定的、對應(yīng)于變量的真實類型main(){

Rectanglerect(1,2);

Shape&sh1=rect;Shape*psh2=newCircle(3);

rect.Show();

sh1.Show();

//正確輸出2

psh2

->Show();

//正確輸出9.42

deletepsh2;

voiduserFunc(constShape&);

userFunc(rect);

}

voiduserFunc(constShape&sh){

sh.Show();

.....

}虛函數(shù)的作用機制--函數(shù)調(diào)用的編譯編譯過程(以p->Func()為例)確定p的靜態(tài)類型,如A*在A類中,尋找名字為Func,且參數(shù)可以匹配的函數(shù)若找不到,編譯錯誤。若找到,該函數(shù)為virtual函數(shù)嗎?若不是,編譯成p->A::Func();若是虛函數(shù),采用動態(tài)編聯(lián),從而編譯成

(*p->vptr)[index]((void*)p);,即在運行時,根據(jù)vptr中的函數(shù)入口地址,選擇執(zhí)行函數(shù)。若希望pObj->Func();或obj.Func();合法,必須有:pObj/obj的靜態(tài)類型中必須有匹配的函數(shù)Func;即使匹配的Func,永遠不被調(diào)用,也要有虛函數(shù)作用機制(例1)classA{public:

virtual~A(){}

virtualvoidf2();

virtualvoidg();};

classB:publicA{public:

virtual

voidf1();

virtual

voidf2();

virtualvoidf3();};p1->f2()編譯成(*p1->vprt)[1]((void*)p1)

p1->g()編譯成(*p1->vprt)[2]((void*)p1)

p2->f2()編譯成(*p2->vprt)[1]((void*)p2)

p2->g()編譯成(*p2->vprt)[2]((void*)p2)deletep2編譯成...;(*p2->vprt)[0]((void*)p2)deletep1編譯成...;(*p1->vprt)[0]((void*)p1)A*p1=newA;

p1->f2();p1->g();p1->f1();

A*p2=newB;

p2->f2();p2->g();p2->f1();deletep2;deletep1;//A類的虛擬表

&A::~A()

&A::f2()

&A::g()//B類的虛擬表

&B::~B()

&B::f2()

&A::g()&B::f1()

&B::f3()vptrvptr虛函數(shù)作用機制(例2)classDate{

public:Date(inty,intm,intd);

virtual~Date(){}

boolIsLeap()const;

virtualvoidDisplay()const{}

protected:

intmYear;

intmMonth;

intmDay;

};classChinaDate:publicDate{

public:

ChinaDate(inty,intm,intd)

:Date(y,m,d){}

virtualvoidDisplay()const{

cout<<mYear<<“年”;

cout<<mMonth<<“月”;

cout<<mDay<<“日”<<endl;

}

protected://other

};classUsaDate:publicDate{

public:

UsaDate(inty,intm,intd)

:Date(y,m,d){}

virtualvoidDisplay()const{

cout<<mMonth<<“/”;

cout<<mDay<<“/”;

cout<<mYear<<endl;

}

//....

};Date*pDate1=

newUsaDate(2008,12,31);

pDate1->Display();//12/31/2008

deletepDate1;Date*pDate2=newChinaDate(2008,12,31);

pDate2->Display();//2008年12月31日

deletepDate2;虛函數(shù)作用機制(例3)classShape{public:

virtual~Shape(){}

voidShow()const{

cout<<“面積是:”<<Area()<<endl;

}

virtualfloatArea()const{return0;}};classCircle:publicShape{public:

Circle(floatr):mRadius(r){}

virtualfloatArea()const{

returnmRadius*mRadius*3.14;

}

private:

floatmRadius;};main(){

Rectanglerect(1,2);

Shape&rRect=rect;Shape*pCircle=newCircle(3);

rRect.Show();//正確輸出2

pCircle->Show();//正確輸出9.42

deletepCircle;

}classRectangle:publicShape{public:

Rectangle(floatw,floath){

mWidth=w;mHeight=h;

}

virtualfloatArea()const{

returnmWidth*mHeight;

}

private:

floatmWidth,mHeight;};虛函數(shù)作用機制(例4)Date應(yīng)用例子:Date*p=newChinaDate(2008,12,31);p->Display();deletep;或

voidFunc(Date*p){p->Display();}intmain(){Date*p=newUsaDate(2008,12,31);Func(p);//輸出12/31/2008deletep;p=newChinaDate(2008,12,31);Func(p);//輸出2008年12月31日deletep;}虛函數(shù)的訪問虛函數(shù)中訪問的非虛函數(shù)靜態(tài)編聯(lián),使用本地版本非虛函數(shù)中訪問的虛函數(shù)動態(tài)編聯(lián)虛函數(shù)中訪問的虛函數(shù)動態(tài)編聯(lián)構(gòu)造函數(shù)和虛函數(shù)構(gòu)造函數(shù)不能為虛函數(shù)調(diào)用的虛函數(shù)采用靜態(tài)編聯(lián),使用本地版本析構(gòu)函數(shù)和虛函數(shù)析構(gòu)函數(shù)可以為虛函數(shù)若類中含有虛函數(shù),那么析構(gòu)函數(shù)也應(yīng)為虛函數(shù).調(diào)用的虛函數(shù)采用靜態(tài)編聯(lián),使用本地版本classA{public:

virtual~A(){}

virtualvoidf(){g();}

virtualvoidg(){k();}

voidk();};

classB:publicA{public:

virtual

voidf(){g();k();}

voidk(){h();}voidh();};A*p1=newA;p1->X();A*p2=newB;p2->X();構(gòu)造/析構(gòu)函數(shù)調(diào)用本地版本的虛函數(shù)classA{

public:

A():mA(100){f();}

virtual~A(){f();}

virtualvoidf()

{cout<<mA;}

private:intmA;

};classB:pulicA{

public:

B():mB(200){}

virtual~B(){f();}

virtualvoidf()

{cout<<mB;}

private:intmB;

};Bb;:先構(gòu)造父類A,調(diào)用本地的f(),即A::f()B

b;:釋放時,先析構(gòu)B類,執(zhí)行B::~B();然后

要析構(gòu)A類,需要執(zhí)行A::~A(),只能調(diào)

用本地的f(),即A::f();虛函數(shù)的訪問(例)classBase{

public:

Base(){vf();}

virtual~Base(){vf();}

virtualvoidvf(){

cout<<“Base::vf()”<<endl;

}

virtualvoidvg(){

cout<<“Base::vg()”<<endl;

vf();

nvh();

}

voidnvh(){

cout<<“Base::nvh()”<<endl;

vf();

}

};classDerived:publicBase{

public:

Derived(){vf();}

virtual~Derived(){vf();}

virtualvoidvf(){

cout<<“Derived::vf()”<<endl;

}

voidnvh(){

cout<<“Derived::nvh”<<endl;

vf();

}

virtualvoidMy(){}

};Base*p=newDerived;

p->vf();

p->vg();

p->nvh();

deletep;抽象類和具體類抽象類和具體類抽象類:不能被實例化具體類:可以實例化純虛函數(shù)(一定是成員函數(shù))格式:virtualReturnTypeFunc(….)[const]=0;抽象類:含有一個或多個純虛函數(shù)。純抽象類:除靜態(tài)、構(gòu)造、析構(gòu)等函數(shù)均為純虛函數(shù).純虛定義:對純虛函數(shù)給出缺省實現(xiàn)(定義)C++中的接口類是純抽象類,且沒有任何數(shù)據(jù)成員。抽象的派生類抽象類(例)classShape1{//抽象類public:virtual~Shape1(){}

voidShow()const

{cout<<“面積是:”<<Area()<<endl;}

virtualfloatArea()const=0;

};classIAreable{//接口類public:

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論