版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年空調(diào)銷售渠道拓展與品牌建設(shè)服務(wù)合同3篇
- 二零二五版合租房屋租賃合同-含裝修保證金條款3篇
- 二零二五版建筑設(shè)備租賃合同書范例2篇
- 二零二五版法院判決指導(dǎo)下的債務(wù)償還與再融資合同3篇
- 二零二五版第5章第5節(jié)合同擔(dān)保及供應(yīng)鏈金融合作協(xié)議3篇
- 二零二五版合同部合同合規(guī)性審查與風(fēng)險預(yù)警合同3篇
- 二零二五年度酒店物業(yè)服務(wù)質(zhì)量持續(xù)改進合同3篇
- 二零二五年青少年體育賽事服裝贊助合同3篇
- 二零二五版安防監(jiān)控設(shè)備研發(fā)與生產(chǎn)合同3篇
- 二零二五年度物流行業(yè)集體合同協(xié)議范本3篇
- 2024年08月云南省農(nóng)村信用社秋季校園招考750名工作人員筆試歷年參考題庫附帶答案詳解
- 防詐騙安全知識培訓(xùn)課件
- 心肺復(fù)蘇課件2024
- 2024年股東股權(quán)繼承轉(zhuǎn)讓協(xié)議3篇
- 2024-2025學(xué)年江蘇省南京市高二上冊期末數(shù)學(xué)檢測試卷(含解析)
- 四川省名校2025屆高三第二次模擬考試英語試卷含解析
- 湖南財政經(jīng)濟學(xué)院專升本管理學(xué)真題
- 2024年認證行業(yè)法律法規(guī)及認證基礎(chǔ)知識
- 江蘇省建筑與裝飾工程計價定額(2014)電子表格版
- Proud-of-you中英文歌詞
- 基因的表達與調(diào)控.ppt
評論
0/150
提交評論