亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        用游戲編程實例進行C++“多態(tài)”概念教學(xué)

        2011-12-31 00:00:00郭煒
        計算機教育 2011年14期


          摘要:“多態(tài)”是面向?qū)ο蟪绦蛟O(shè)計方法中的重要概念,也是提高程序可擴充性的重要手段。然而初學(xué)面向?qū)ο缶幊痰膶W(xué)生往往難以真正體會到其作用。文章介紹一個在教學(xué)中沿用多年,能夠生動而充分地展示多態(tài)的作用,并在教學(xué)比賽中獲獎的游戲編程教學(xué)案例,供大家參考。
          關(guān)鍵詞:多態(tài);可擴充性;虛函數(shù);抽象類
          
          1問題的提出
          面向?qū)ο蟪绦蛟O(shè)計語言有封裝、繼承和多態(tài)三種機制,這三種機制能夠有效提高程序的可讀性、可擴充性和可重用性。
          而“多態(tài)”(Polymorphism),可以分為編譯時的多態(tài)和運行時的多態(tài)。
          編譯時的多態(tài),主要指的是運算符的重載和函數(shù)的重載。這部分內(nèi)容,比較簡單,易于理解,本文并不打算討論。
          運行時的多態(tài),指的是以下機制(本文以后提到的“多態(tài)”,都指的是運行時的多態(tài)):
          對于通過基類指針,調(diào)用基類和派生類中都有的同名、同參數(shù)表的虛函數(shù)這樣的語句,編譯時并不確定要執(zhí)行的是基類還是派生類的虛函數(shù);而當(dāng)程序運行到該語句時,如果該基類指針指向的是一個基類對象,則基類的虛函數(shù)被執(zhí)行,如果該基類指針指向的是一個派生類對象,則派生類的虛函數(shù)被執(zhí)行(將上面表述中的“指針”換成“引用”,同樣成立)。
          多態(tài)可以簡單地理解成同一條函數(shù)調(diào)用語句能調(diào)用不同的函數(shù),或者說,對不同對象發(fā)送同一消息,使得不同對象有各自不同的行為。
          多態(tài)在面向?qū)ο蟮某绦蛟O(shè)計語言中是如此重要,以至于有類和對象的概念,但是不支持多態(tài)的語言,只能被稱作“基于對象的程序設(shè)計語言”,而不能被稱為“面向?qū)ο蟮某绦蛟O(shè)計語言”。如Visual Basic就是“基于對象的程序設(shè)計語言”。
          讓學(xué)生掌握多態(tài)的語法規(guī)則并不難,難的是讓他們深刻理解多態(tài)到底有什么用處。實際上,在面向?qū)ο蟮木幊讨惺褂枚鄳B(tài),能夠有效地提高程序的可擴充性,這就是多態(tài)最大的作用。
          所謂一個程序的可擴性好,指的就是當(dāng)該程序的功能需要增加或修改時,只需改動或增加比較少的代碼就能實現(xiàn)。往往,一個程序員只有在編寫了一定規(guī)模的程序,并且等到其程序真正需要添加新功能的時候,才能切身體會到程序的可擴充性是多么重要。那么,怎樣才能讓沒有多少編程經(jīng)歷的低年級學(xué)生,不需要編寫大規(guī)模的程序就能體會到多態(tài)在提高程序可擴充性方面的作用呢?這就是本文要探討的問題。
          2問題的現(xiàn)狀
          筆者查閱多本流行的C++教材,這些教材和講義大多對多態(tài)提高程序的可擴充性這個作用未能充分展示。這些教材在闡述多態(tài)時,所舉的例子一般都是這樣的:
          開設(shè)一個基類指針數(shù)組,該數(shù)組里的指針,有的指向基類對象,有的指向派生類對象。在此種情況下,遍歷該數(shù)組,對每個數(shù)組元素,均通過它去調(diào)用基類和派生類里都有的同名虛函數(shù),這就達到了在每個對象上都執(zhí)行它自己的虛函數(shù)的目的[2]。例如,一個幾何形體演示程序,有基類Shape,還有Rectangle,Triangle和Circle等Shape的派生類,這些類都有虛函數(shù)double Area()用以計算圖形的面積。那么要計算所有幾何圖形的面積,只需用一個Shape * 類型的數(shù)組,存放所有幾何圖形對象的地址,然后遍歷該數(shù)組,對每個元素(即類型為Shape * 的變量)均通過它去調(diào)用Area()虛函數(shù),那么多態(tài)機制就能確保每個幾何圖形的面積都是用正確的Area()函數(shù)計算出來的[3]。
          這樣的例子,說明使用多態(tài)能夠某種程度上精簡程序的代碼,但不能很好地說明多態(tài)在增強可擴充性方面的作用。比較好的例子應(yīng)該是用多態(tài)和非多態(tài)的方法各寫一段程序,然后要求對該程序進行功能上的擴充,此時再來看這兩段程序各要做多大的改動——這才能夠充分體現(xiàn)多態(tài)的優(yōu)勢。
          筆者看到的教材里,只有一部采用了這樣的寫法[1]。該書舉了一個異質(zhì)鏈表(同一鏈表里存放不同類型的對象)的例子。該例子能夠充分說明多態(tài)的優(yōu)點,但是略顯冗長,不夠生動有趣,也不像實踐中的例子。
          那么軟件開發(fā)的實踐中,能否找到生動有趣而又不冗長的例子,來充分說明多態(tài)在程序可擴充性方面的作用呢?答案是肯定的,那就是到游戲開發(fā)中去尋找案例。
          3問題的解決
          游戲軟件的開發(fā),是最能體現(xiàn)面向?qū)ο笤O(shè)計方法的優(yōu)勢的。游戲中的人物、道具、建筑物、場景,都是很直觀的對象,游戲運行的過程,就是這些對象相互作用的過程。每個對象都有自己的屬性和方法,不同對象又可能有共同的屬性和方法,特別適合使用繼承、多態(tài)等面向?qū)ο蟮臋C制。而且,游戲本來就是學(xué)生所津津樂道的,在課堂的PPT里放幾張游戲的截圖,學(xué)生精神就會為之一振,興趣大增。因此,筆者在講述“多態(tài)”這一概念的時候,以“魔法門之英雄無敵”游戲的開發(fā)為例,充分論述了多態(tài)在提高程序可擴充性方面的作用,讓同學(xué)們不但能學(xué)得明白,還能學(xué)得有趣。
          “魔法門”游戲中有各種各樣的怪物,如騎士、天使、狼,鬼,等等。每個怪物都有生命力、攻擊力這兩種屬性。怪物能夠互相攻擊,一個怪物攻擊另一個怪物時,會使被攻擊者受傷;同時被攻擊者會反擊,使得攻擊者也受傷。但是一個怪物反擊的力量較弱,只是其自身攻擊力的1/2。
          怪物主動攻擊、被敵人攻擊和實施反擊時都有相應(yīng)的動作。比如騎士攻擊時的動作就是揮舞寶劍,而火龍的攻擊動作就是噴火;怪物受到攻擊會嚎叫和受傷流血,如果受傷過重,生命力被減為0,則怪物就會倒地死去…….
          針對這個游戲,教師提出的問題是:該如何編寫程序,才能使得游戲版本升級,要增加新的怪物時,原有的程序改動盡可能少 。換句話說,就是怎樣才能使程序的可擴充性更好。
          顯然,不論是否使用多態(tài),均應(yīng)使每種怪物都有一個類與之對應(yīng),每個怪物就是一個對象。而且,怪物的攻擊、反擊和受傷等動作,都是通過對象的成員函數(shù)實現(xiàn)的,因此為每個類都需要編寫Attack、FightBack和 Hurted成員函數(shù)
          Attact函數(shù)表現(xiàn)攻擊動作,攻擊某個怪物,并調(diào)用被攻擊怪物的 Hurted函數(shù),以減少被攻擊怪物的生命值,同時也調(diào)用被攻擊怪物的 FightBack成員函數(shù),遭受被攻擊怪物反擊。
          Hurted函數(shù)減少自身生命值,并表現(xiàn)受傷動作。
          FightBack成員函數(shù)表現(xiàn)反擊動作,并調(diào)用被反擊對象的Hurted成員函數(shù),使被反擊對象受傷。
          接下來就是對比使用多態(tài)和不使用多態(tài)兩種寫法,來體現(xiàn)多態(tài)在提高程序可擴充性方面的作用。
          先看不用多態(tài)的寫法。假定用“CDragon”類表示火龍,用“CWolf”類表示狼,用“CGhost”類表示鬼,則“CDragon”類寫法大致如下(其他類的寫法也類似):
          
          class CDragon
          {
          private:
          int m_nPower ; //攻擊力
          int m_nLifeValue ; //生命值
          public:
          //攻擊“狼”的成員函數(shù)
          void Attack(CWolf * p);
          //攻擊“鬼”的成員函數(shù)
          void Attack(CGhost * p);
          //......其他Attack重載函數(shù)
          //表現(xiàn)受傷的成員函數(shù)
          void Hurted( int nPower);
          //反擊“狼”的成員函數(shù)
          void FightBack(CWolf * p);
          //反擊“鬼”的成員函數(shù)
          void FightBack(CGhost * p);
          
          //......其他FightBack重載函數(shù)
          };
          
          接下來再看各成員函數(shù)的寫法:
          
          1.void CDragon::Attack(CWolf * p)
          2.{
          3.p->Hurted(m_nPower);
          4. p->FightBack(this);
          5.}
          6.void CDragon::Attack(CGhost * p)
          7.{
          8. p->Hurted(m_nPower);
          9. p->FightBack(this);
          10.}
          11.void CDragon::Hurted(int nPower)
          12.{
          13.m_nLifeValue -= nPower;
          14.}
          15.void CDragon::FightBack(CWolf * p)
          16.{
          17. p->Hurted(m_nPower/2);
          18.}
          19.void CDragon::FightBack(CGhost * p)
          20.{
          21.p->Hurted(m_nPower/2);
          22.}
          
          在上面帶行號的程序中:
          第1行,Attack函數(shù)的參數(shù)p,指向被攻擊的CWolf對象。
          第3行,在p所指向的對象上面執(zhí)行Hurted成員函數(shù),使被攻擊的“狼”對象受傷。調(diào)用Hurted時,參數(shù)是攻擊者“龍”對象的攻擊力。
          第4行,以指向攻擊者自身的this指針為參數(shù),調(diào)用被攻擊者的FightBack成員函數(shù),接受被攻擊者的反擊。
          顯然,在真實的游戲程序中,CDragon類的Attack成員函數(shù)中還應(yīng)包含表現(xiàn)火龍在攻擊時的動作和聲音的代碼。
          第13行,一個對象的Hurted成員函數(shù)被調(diào)用會導(dǎo)致該對象的生命值減少,減少的量等于攻擊者的攻擊力。當(dāng)然,真實的程序中,Hurted函數(shù)還應(yīng)包含表現(xiàn)受傷時動作的代碼,以及生命力如果減至小于等于零,則倒地死去的代碼。
          第17行,p指向的是實施攻擊者,對攻擊者進行反擊,實際上就是調(diào)用攻擊者的Hurted成員函數(shù)使其受傷。其受到的傷害的大小,等于實施反擊者的攻擊力的一半(反擊的力量不如主動攻擊大)。當(dāng)然,F(xiàn)ightBack函數(shù)中其實也應(yīng)包含表現(xiàn)反擊動作的代碼。
          實際上,如果游戲中有n種怪物,CDragon 類中就會有n個Attack成員函數(shù),用于攻擊n種怪物。當(dāng)然,也會有n個FightBack成員函數(shù)(這里我們假設(shè)兩條龍也能互相攻擊)。對于其他類,比如CWolf等,也是這樣
          以上為非多態(tài)的實現(xiàn)方法。如果游戲版本升級,增加了新的怪物雷鳥,假設(shè)其類名為CThunderBird, 則程序需要做哪些改動呢?
          顯然,除了新寫一個CThunderBird類外,所有的類都需要增加以下兩個成員函數(shù),用以對雷鳥實施攻擊,以及在被雷鳥攻擊時對其進行反擊:
          
          void Attack( CThunderBird * p) ;
          void FightBack( CThunderBird * p) ;
          
          這樣,在怪物種類多的時候,工作量就較大。
          實際上,非多態(tài)實現(xiàn)中,代碼更精簡的做法是將CDragon,CWolf等類的共同特點抽取出來,形成一個CCreature類,然后再從CCreature類派生出CDragon、CWolf等類。但是由于每種怪物進行攻擊、反擊和受傷時的表現(xiàn)動作不同,CDragon、CWolf這些類還是要實現(xiàn)各自的Hurted成員函數(shù),以及一系列Attack、FightBack成員函數(shù)。所以只要沒有利用多態(tài)機制,那么即便引入基類CCreature,對程序的可擴充性也無幫助。
          下面再來看看,如果使用多態(tài)機制來編寫這個程序,在要新增CThunderBird類的時候,程序改動有多大。
          多態(tài)的寫法如下:
          設(shè)置一個抽象類CCreature,概括了所有怪物的共同特點。然后,所有具體的怪物類,比如CDragon,CWolf,CGhost等,均從CCreature類派生而來。
          下面是CCreature類的寫法:
          
          class CCreature{
          protected :
          int m_nLifeVa

        欧美多人片高潮野外做片黑人| 中文字幕久久熟女人妻av免费| av网站不卡的av在线| 国产极品粉嫩福利姬萌白酱| 国产精品va无码一区二区| 日韩精品欧美激情亚洲综合| 日本熟女视频一区二区三区| 末成年人av一区二区| 黑人巨大跨种族video| 久久九九有精品国产尤物| 亚洲中文字幕在线精品2021| 亚洲中文字幕人妻av在线| 国产午夜精品理论片| 国模精品二区| 国产精品亚洲精品专区| 欧美巨鞭大战丰满少妇| 99久久久精品免费观看国产| 免费二级毛片在线播放| 亚洲国产av高清一区二区三区| 久久久久人妻一区二区三区| 国产精品99久久久久久宅男| 国产AV秘 无码一区二区三区| 97青草超碰久久国内精品91| 亚洲国产av无码专区亚洲av| 中文字幕第1页中文字幕在| av成人资源在线播放| 东北女人啪啪对白| 中文亚洲成a人片在线观看| 国产精品无码久久久久久久久作品 | 日本一区二区三区啪啪| 91精品国产乱码久久中文| 人人摸人人操| 国产综合久久久久影院| 亚洲成人av一区二区| 一级黄片草逼免费视频| 狠狠cao日日橹夜夜十橹| 久久久久久久久久久国产| 国产成人福利在线视频不卡 | 色欲色香天天天综合vvv| 国产在线观看免费观看| 国产杨幂AV在线播放|