C++:类-多态的学习和使用
C++:類的學(xué)習(xí)和使用
- 類的多態(tài)
- 1.類的實(shí)例化
- 1.類中虛函數(shù)的使用實(shí)現(xiàn)多態(tài)
- C++ override使用詳解
類的多態(tài)
類作用域操作符 ::
C++是面向?qū)ο蟮木幊陶Z言,多態(tài)的使用是父類與子類關(guān)系最直接的表現(xiàn):
c++中對于多態(tài)的理解就好比如下一個例子:
①我們說一種有四條腿的動物A,并進(jìn)行簡單描述有四條腿的特征;
②甲猜了一種動物B,并且說了四條腿的具體特征;
③乙猜了一種動物C,并且說了四條腿的具體特征;
如上:動物A可以理解為基類,動物B.C都是子類,所以類的多態(tài)就表現(xiàn)在四條腿的特征(父類的(純)虛函數(shù))上 B和C都繼承了A四條腿的特征,至于B和C因?yàn)楦髯晕锓N差異而有所不同就對應(yīng)了具體的子類中的(純)虛函數(shù)定義。
https://blog.csdn.net/lling_shan/article/details/105947287
分類:
靜態(tài)多態(tài)
:靜態(tài)多態(tài)是編譯器在編譯期間完成的,編譯器會根據(jù)實(shí)參類型來選擇調(diào)用合適的函數(shù),如果有合適的函數(shù)可以調(diào)用就調(diào),沒有的話就會發(fā)出警告或者報錯。
動態(tài)多態(tài)
:程序運(yùn)行時根據(jù)基類的引用(指針)指向的對象來確定自己具體該調(diào)用哪一個類的虛函數(shù)
靜態(tài)多類:
/** 程序名:book236.cpp,此程序用于演示C++類的靜態(tài)多態(tài)。* 作者:C語言技術(shù)網(wǎng)(www.freecplus.net) 日期:20190525 */ #include <stdio.h> #include <string.h>class CGirl // 定義超女類 { public:char m_name[50]; // 姓名int m_age; // 年齡int m_height; // 身高,單位:厘米cmchar m_sc[30]; // 身材,火辣;普通;飛機(jī)場。char m_yz[30]; // 顏值,漂亮;一般;歪瓜裂棗。int Show() // 顯示超女基本信息的成員函數(shù)體{ printf("姓名:%s,年齡:%d,身高:%d,身材:%s,顏值:%s\n",m_name,m_age,m_height,m_sc,m_yz); } };class CKCon:public CGirl // 定義王妃類,從超女類繼承 { public:char m_ch[50]; // 稱號char m_palace[50]; // 居住的宮殿int m_sal; // 奉祿int Show() // 顯示王妃的稱號、宮殿和奉祿{ printf("姓名:%s,稱號:%s,棲:%s,奉祿:%d兩銀子。\n",m_name,m_ch,m_palace,m_sal); } };int main() {CKCon KCon;strcpy(KCon.m_name,"楊玉環(huán)"); KCon.m_age=28; KCon.m_height=168;strcpy(KCon.m_sc,"火辣"); strcpy(KCon.m_yz,"漂亮"); strcpy(KCon.m_ch,"楊貴妃");strcpy(KCon.m_palace,"華清宮"); KCon.m_sal=10000;CGirl *pGirl; // 基類的指針CKCon *pCon; // 派生類的指針pGirl=pCon=&KCon; // 都指向派生類pGirl->Show(); // 將調(diào)用的是基類的Show方法pCon->Show(); // 將調(diào)用的是派生類的Show方法 }輸出結(jié)果:
main函數(shù)中,創(chuàng)建的是CKCon對象,如果采用基類指針調(diào)用Show方法,變成了調(diào)用CGirl類的Show方法,而不是CKcon類的Show方法,因?yàn)閜Girl是CGirl的指針,pGirl->Show方法在程序編譯期間就已經(jīng)設(shè)置好了。
動態(tài)多態(tài):
動態(tài)多態(tài)是在程序運(yùn)行時根據(jù)基類的引用(指針)指向的對象來確定自己具體該調(diào)用哪一個類的虛函數(shù)。
讓我們對程序稍作修改,在CGirl類中,Show方法的聲明前放置關(guān)鍵字 virtual,如下所示:
virtual int Show() // 顯示超女基本信息的成員函數(shù)體其它的代碼都不變,編譯并運(yùn)行,結(jié)果如下:
此時,編譯器看的是指針的內(nèi)容,而不是它的類型。這就是多態(tài)的一般使用方式。
1.類的實(shí)例化
https://blog.csdn.net/qq_34637408/article/details/71189382
1.類中虛函數(shù)的使用實(shí)現(xiàn)多態(tài)
①類的多態(tài)
②1.首先看成員函數(shù)所在的類是否會作為基類。然后看成員函數(shù)在類的繼承后有無可能被更改功能,如果希望更改其功能的,一般應(yīng)該將它聲明為虛函數(shù)。
3、應(yīng)考慮對成員函數(shù)的調(diào)用時通過對象名還是通過基類指針或引用去訪問,如果是通過基類指針或引用去訪問的,則應(yīng)當(dāng)聲明為虛函數(shù)。
4.有時,在定義虛函數(shù)時,并不定義去函數(shù)體,即函數(shù)體是空的。它的作用只是定義了一個虛函數(shù)名,具體功能留給派生類去添加。
使用虛函數(shù),系統(tǒng)要有一定的空間開銷。當(dāng)一個類帶有虛函數(shù)時,編譯系統(tǒng)會為該類構(gòu)造一個虛函數(shù)表,它是一個指針數(shù)組,存放每個虛函數(shù)的入口地址。系統(tǒng)在進(jìn)行動態(tài)關(guān)聯(lián)時的時間開銷時很小的,因此,多態(tài)性時高效的。
原文鏈接:https://blog.csdn.net/wshngyf/article/details/48092679
純虛函數(shù)
一、定義
純 虛函數(shù) 是一種特殊的虛函數(shù),它的一般格式如下:
在許多情況下,在基類中不能對虛函數(shù)給出有意義有實(shí)現(xiàn),而把它說明為純虛函數(shù),它的實(shí)現(xiàn)留給該基類的派生類去做。這就是純虛函數(shù)的作用。
二、引入原因
1、為了方便使用 多態(tài) 特性,我們常常需要在基類中定義虛擬函數(shù)。
2、在很多情況下,基類本身生成對象是不合情理的。
例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身生成對象明顯不合常理。
為了解決上述問題,引入了純虛函數(shù)的概念,將函數(shù)定義為純虛函數(shù)(方法:virtual ReturnType Function()= 0;),則編譯器要求在派生類中必須予以重載以實(shí)現(xiàn)多態(tài)性。同時含有純虛擬函數(shù)的類稱為 抽象類 ,它不能生成對象。這樣就很好地解決了上述兩個問題。
三、相似概念
1、多態(tài)性
指相同對象收到不同消息或不同對象收到相同消息時產(chǎn)生不同的實(shí)現(xiàn)動作。
C++支持兩種多態(tài)性:編譯時多態(tài)性,運(yùn)行時多態(tài)性。
a.編譯時多態(tài)性:通過重載函數(shù)實(shí)現(xiàn)
b 運(yùn)行時多態(tài)性:通過虛函數(shù)實(shí)現(xiàn)。
2、虛函數(shù)
虛函數(shù)是在基類中被聲明為virtual,并在派生類中重新定義的成員函數(shù),可實(shí)現(xiàn)成員函數(shù)的動態(tài)重載
3、抽象類
包含純虛函數(shù)的類稱為抽象類。
由于抽象類包含了沒有定義的純虛函數(shù),所以不能定義抽象類的對象。
注意:
(1)純虛函數(shù)沒有函數(shù)體;
(2)最后面的“=0”并不表示函數(shù)返回值為0,它只起形式上的作用,告訴編譯系統(tǒng)“這是虛函數(shù)”;
(3)這是一個聲明語句,最后有分號。
純虛函數(shù)只有函數(shù)的名字而不具備函數(shù)的功能,不能被調(diào)用。
純虛函數(shù)的作用是在基類中為其派生類保留一個函數(shù)的名字,以便派生類根據(jù)需要對他進(jìn)行定義。如果在基類中沒有保留函數(shù)名字,則無法實(shí)現(xiàn)多態(tài)性。
如果在一個類中聲明了純虛函數(shù),在其派生類中沒有對其函數(shù)進(jìn)行定義,則該虛函數(shù)在派生類中仍然為純虛函數(shù)。
抽象類:
不用定義對象而只作為一種基本類型用作繼承的類叫做抽象類(也叫接口類),凡是包含純虛函數(shù)的類都是抽象類,抽象類的作用是作為一個類族的共同基類,為一個類族提供公共接口,抽象類不能實(shí)例化出對象。
純虛函數(shù)在派生類中重新定義以后,派生類才能實(shí)例化出對象。
總結(jié):
1、派生類重寫基類的虛函數(shù)實(shí)現(xiàn)多態(tài),要求函數(shù)名、參數(shù)列表、返回值完全相同。(協(xié)變除外)
2、基類中定義了虛函數(shù),在派生類中該函數(shù)始終保持虛函數(shù)的特性。
3、只有類的非靜態(tài)成員函數(shù)才能定義為虛函數(shù),靜態(tài)成員函數(shù)不能定義為虛函數(shù)。
4、如果在類外定義虛函數(shù),只能在聲明函數(shù)時加virtual關(guān)鍵字,定義時不用加。
5、構(gòu)造函數(shù)不能定義為虛函數(shù),雖然可以將operator=定義為虛函數(shù),但最好不要這么做,使用時容易混淆
6、不要在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù),在構(gòu)造函數(shù)和析構(gòu)函數(shù)中,對象是不完整的,可能會出現(xiàn)未定義的行為。
7、最好將基類的析構(gòu)函數(shù)聲明為虛函數(shù)。(析構(gòu)函數(shù)比較特殊,因?yàn)榕缮惖奈鰳?gòu)函數(shù)跟基類的析構(gòu)函數(shù)名稱不一樣,但是構(gòu)成覆蓋,這里編譯器做了特殊處理)
8、虛表是所有類對象實(shí)例共用的虛表剖析。
原文鏈接:https://blog.csdn.net/qq_36221862/article/details/61413619
class A{public:A();virtual ~A();void f1();virtual void f2();virtual void f3()=0;};//子類:class B : public A{public:B();virtual ~B();void f1();virtual void f2();virtual void f3();};// main 函數(shù):int main(int argc, char* argv[]){A *m_j=new B();m_j->f1();m_j->f2();m_j->f3();delete m_j;return 0;}f1()是一個隱藏,關(guān)于函數(shù)的隱藏,可以參考其它詞條.
調(diào)用m_j->f1();會去調(diào)用A類中的f1(),它是在我們寫好代碼的時候就會定好的.
也就是根據(jù)它是由A類定義的,這樣就調(diào)用這個類的函數(shù).
f2()是普通的重載.
調(diào)用m_j->f2();會調(diào)用m_j中到底保存的對象中,對應(yīng)的這個函數(shù).這是由于new的B對象.
f3()與f2()一樣,只是在基類中不需要寫函數(shù)實(shí)現(xiàn).
虛函數(shù)和抽象基類的應(yīng)用:
#include <iostream> using namespace std;//聲明抽象基類Shape class Shape { public:virtual float area()const //虛函數(shù){return 0.0;}virtual void shapeName()const = 0;//純虛函數(shù)//shapeNamea函數(shù)的作用是輸出具體的形狀,在派生類中定義,因此聲明為純虛函數(shù) };//聲明Point類 class Point:public Shape { public:Point(float a = 0.0, float b = 0.0){x = a;y = b;}void setPoint(float a, float b){x = a;y = b;}float getX()const{return x;}float getY()const{return y;}virtual void shapeName()const{cout<<"Point:";}friend ostream & operator <<(ostream &_cout, const Point &p){_cout<<"["<<p.x<<","<<p.y<<"]";return _cout;}protected:float x;float y; };//聲明Ciircle類 class Circle:public Point { public:Circle(float a = 0.0, float b = 0.0, float r = 0.0):Point(a, b),radius(r){}void setRadius(float r){radius = r;}float getRadius()const{return radius;}virtual float area()const{return 3.1415926*radius*radius;}virtual void shapeName()const{cout<<"Circle:";}friend ostream & operator <<(ostream &_cout, const Circle &c){_cout<<"["<<c.x<<","<<c.y<<"],r="<<c.radius;return _cout;}protected:float radius; };int main() {Point point(3.2, 4.5); // 建立Point類對象pointCircle circle(2.4, 1.2, 5.6); //建立Circle類對象circlepoint.shapeName(); //靜態(tài)關(guān)聯(lián)cout<<point<<endl;circle.shapeName(); //靜態(tài)關(guān)聯(lián)cout<<circle<<endl;Shape* pt; //定義基類指針pt = &point;pt->shapeName();cout<<"x="<<point.getX()<<",y="<<point.getY()<<endl;cout<<"area="<<pt->area()<<endl;pt = &circle; //指針指向Circle類對象pt->shapeName(); //動態(tài)關(guān)聯(lián)cout<<"x="<<circle.getX()<<",y="<<circle.getY()<<endl;cout<<"area="<<pt->area()<<endl;system("pause");return 0; }運(yùn)行結(jié)果
結(jié)論:
(1)一個基類如果包含一個或一個以上純虛函數(shù),就是抽象基類。抽象基類不能也沒必要定義對象。
(2)在類的層次結(jié)構(gòu)中,頂層或最上面幾層可以是抽象基類。抽象基類體現(xiàn)了本類族中各類的共性,把各類中共有的成員函數(shù)集中在抽象基類中聲明。
(3)抽象基類是本類族的共公共接口,即就是從同一基類中派生出的多個類有同一接口。
原文鏈接:https://blog.csdn.net/qq_36221862/article/details/61413619
C++ override使用詳解
C++ override從字面意思上,是覆蓋的意思,實(shí)際上在C++中它是覆蓋了一個方法并且對其重寫,從而達(dá)到不同的作用。在我們C++編程過程中,最熟悉的就是對接口方法的實(shí)現(xiàn),在接口中一般只是對方法進(jìn)行了聲明,而我們在實(shí)現(xiàn)時,就需要實(shí)現(xiàn)接口聲明的所有方法。還有一個典型應(yīng)用就是在繼承中也可能會在子類覆蓋父類的方法。
原文鏈接:https://blog.csdn.net/fanyun_01/article/details/79122136
總結(jié)
以上是生活随笔為你收集整理的C++:类-多态的学习和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【图像处理】纹理检测算法
- 下一篇: s3c2440移植MQTT