大家都知道多態(tài)是面向?qū)ο缶幊痰囊粋€(gè)特性,簡單點(diǎn)說:“一個(gè)接口,多種實(shí)現(xiàn)”,就是同一種事物表現(xiàn)出的多種形態(tài)。所有的面向?qū)ο缶幊痰恼Z言都有以下三種特性:繼承、封裝、多態(tài)。接下來我們要詳細(xì)的聊一聊C++中的多態(tài)是如何應(yīng)用的。
創(chuàng)新互聯(lián)長期為上1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為曾都企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì),曾都網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。1.定義我們來看下面一個(gè)例子:
#includeusing namespace std;
class Shape {protected:
int width, height;
public:
Shape( int a=0, int b=0)
{ width = a;
height = b;
}
virtual int area() // virtual是用來定義虛函數(shù)的,是C++繼承里不可缺少的關(guān)鍵字,如果不用它,那么我們就不會(huì)達(dá)到多態(tài)的效果,我們調(diào)用的依然是基類的方法。
{ cout<< "Parent class area :"<public:
Rectangle( int a=0, int b=0):Shape(a, b) {}
int area ()
{ cout<< "Rectangle class area :"<public:
Triangle( int a=0, int b=0):Shape(a, b) {}
int area ()
{ cout<< "Triangle class area :"<Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// 存儲(chǔ)矩形的地址
shape = &rec;
// 調(diào)用矩形的求面積函數(shù) area
shape->area();
// 存儲(chǔ)三角形的地址
shape = &tri;
// 調(diào)用三角形的求面積函數(shù) area
shape->area();
return 0;
}
2.作用多態(tài)的定義格式:就是父類的引用變量指向子類對象
父類類型 變量名 = new 子類類型();
變量名.方法名();
4.多態(tài)存在的必要條件虛函數(shù)是C++類繼承中必不可少的概念,我們要學(xué)好C++類的使用,就必須深刻的掌握虛函數(shù)
5.1 虛函數(shù)虛函數(shù) 是在基類中使用關(guān)鍵字 virtual 聲明的函數(shù)。在派生類中重新定義基類中定義的虛函數(shù)時(shí),會(huì)告訴編譯器不要靜態(tài)鏈接到該函數(shù)。
我們想要的是在程序中任意點(diǎn)可以根據(jù)所調(diào)用的對象類型來選擇調(diào)用的函數(shù),這種操作被稱為動(dòng)態(tài)鏈接,或后期綁定。
5.2 純虛函數(shù)您可能想要在基類中定義虛函數(shù),以便在派生類中重新定義該函數(shù)更好地適用于對象,但是您在基類中又不能對虛函數(shù)給出有意義的實(shí)現(xiàn),這個(gè)時(shí)候就會(huì)用到純虛函數(shù)。
我們可以把基類中的虛函數(shù) area() 改寫如下:
class Shape {protected:
int width, height;
public:
Shape( int a=0, int b=0)
{ width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
= 0 告訴編譯器,函數(shù)沒有主體,上面的虛函數(shù)是純虛函數(shù)。
5.3 抽象類當(dāng)一個(gè)類中存在了純虛函數(shù),那么這個(gè)類就被稱做抽象類
抽象類特點(diǎn):
class Animal
{public:
Animal()
{cout<< "調(diào)用Animal的構(gòu)造函數(shù)"<< endl;
}
virtual void speak() = 0;
~Animal()
{cout<< "調(diào)用Animal 的析構(gòu)函數(shù)"<< endl;
}
};
{cout<< "調(diào)用Animal的析構(gòu)函數(shù)"<< endl;
}
class Cat :public Animal
{public:
Cat(string name)
{cout<< "調(diào)用Cat的構(gòu)造函數(shù)"<< endl;
_name = new string(name);
}
virtual void speak()
{cout<< *_name<<"貓會(huì)說話"<< endl;
}
string* _name;
~Cat()
{cout<< "調(diào)用Cat的析構(gòu)函數(shù)"<< endl;
if (_name != NULL)
{ delete _name;
}
}
};
void test()
{Animal* c = new Cat("Tom");
c->speak();
delete c;
}
int main()
{test();
return 0;
}
// 輸出結(jié)果:
調(diào)用Animal的構(gòu)造函數(shù)
調(diào)用Cat的構(gòu)造函數(shù)
Tom貓會(huì)說話
調(diào)用Animal的析構(gòu)函數(shù)
我們發(fā)現(xiàn)當(dāng)刪除c對象時(shí),沒有調(diào)用子類中的析構(gòu)函數(shù),而子類中又申請了堆上的空間,那么這樣就會(huì)造成內(nèi)存泄漏。
那么我們?nèi)绾伪WC調(diào)用子類中的析構(gòu)函數(shù)呢?
這里我們就需要在父類的析構(gòu)函數(shù)前面加上virtual來修飾,將父類析構(gòu)函數(shù)做如下修改
//虛析構(gòu)和純虛析構(gòu)都需要代碼的實(shí)現(xiàn)
virtual ~Animal()
{cout<< "調(diào)用Animal的析構(gòu)函數(shù)"<< endl;
}
// 輸出結(jié)果:
調(diào)用Animal的構(gòu)造函數(shù)
調(diào)用Cat的構(gòu)造函數(shù)
Tom貓會(huì)說話
調(diào)用Cat的析構(gòu)函數(shù)
調(diào)用Animal的析構(gòu)函數(shù)
上面我們使用的是虛析構(gòu)函數(shù)來幫助我們解決內(nèi)存泄漏的問題,這里我們也可以使用純析構(gòu)函數(shù)來幫助我們,將父類的析構(gòu)函數(shù)改成:
virtual ~Animal() = 0;
我們這樣寫,程序會(huì)報(bào)錯(cuò),原因是我們沒有定義父類中的純虛析構(gòu)函數(shù),加上定義
Animal::~Animal()
{cout<< "調(diào)用Animal的析構(gòu)函數(shù)"<< endl;
}
當(dāng)在類外實(shí)現(xiàn)了純虛析構(gòu)的實(shí)現(xiàn),編譯器就不再會(huì)報(bào)錯(cuò)
總結(jié):
純虛析構(gòu)函數(shù)和虛析構(gòu)函數(shù)的共性:
純虛析構(gòu)函數(shù)和虛析構(gòu)函數(shù)的不同:
**注:**如果子類中沒有堆區(qū)的數(shù)據(jù),可以不用寫純虛析構(gòu)或者虛析構(gòu)
6.多態(tài)的底層原理有繼承關(guān)系
子類要重寫父類中的虛函數(shù)
有虛函數(shù)的類中會(huì)產(chǎn)生一個(gè)vfptr的指針和一個(gè)名為vftable的作用域,這個(gè)指針指向這個(gè)作用域,而在這個(gè)作用域中存在著被virtual修飾的函數(shù)的地址,如果沒有重寫父類中的虛函數(shù),那么在子類將繼承父類中的vftable,那么在調(diào)用speak函數(shù)時(shí),永遠(yuǎn)調(diào)用的是父類中實(shí)現(xiàn)的函數(shù)。
靜態(tài)綁定
在編譯階段能夠確定方法在內(nèi)存什么位置的就叫靜態(tài)綁定,當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒有,則編譯不通過;如果有,編譯通過。
動(dòng)態(tài)綁定
在運(yùn)行階段,父類對象類型在堆內(nèi)存中創(chuàng)建的實(shí)際對象是子類對象,根據(jù)內(nèi)存中真實(shí)的對象引用重新去給父類的方法表索引項(xiàng)賦值,這種通過程序運(yùn)行過程動(dòng)態(tài)創(chuàng)建對象方法表的定位方法的方式,一般稱之為動(dòng)態(tài)綁定。
向上轉(zhuǎn)型
子類引用的對象轉(zhuǎn)換為父類類型稱為向上轉(zhuǎn)型。就是是將子類對象看成父類對象。此處父類對象可以是接口。
向下轉(zhuǎn)型:把父類對象轉(zhuǎn)為子類對象。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站名稱:C++中多態(tài)使用詳細(xì)講解-創(chuàng)新互聯(lián)
文章鏈接:http://www.rwnh.cn/article32/dcdosc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、網(wǎng)站導(dǎo)航、軟件開發(fā)、定制開發(fā)、定制網(wǎng)站、網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容