◆沈 煒 莊巧莉
(浙江理工大學(xué)信息電子學(xué)院)
基于內(nèi)部視角的C++面向?qū)ο蠼虒W(xué)實踐
◆沈 煒 莊巧莉
(浙江理工大學(xué)信息電子學(xué)院)
面向?qū)ο蟪绦蛟O(shè)計是計算機專業(yè)學(xué)生的重要基礎(chǔ)課,絕大多數(shù)高等院校都以 C++作為面向?qū)ο蟪绦蛟O(shè)計這門課程的教學(xué)語言。應(yīng)該看到,面向?qū)ο蠹夹g(shù)的實現(xiàn)是有著嚴密的技術(shù)體系結(jié)構(gòu)的,教學(xué)的過程,也是這一體系結(jié)構(gòu)向?qū)W生逐步展示,讓學(xué)生逐步理解并掌握的過程。但在具體的教學(xué)過程中,卻有著很多的概念和方法,十分難以理解和掌握。其中,有些內(nèi)容,甚至連教科書都出現(xiàn)自相矛盾的情況。如何采用更為有效的教學(xué)方法,避免出現(xiàn)類似的情況,實現(xiàn)良好的教學(xué)效果,是一個需要重點關(guān)注的問題。另一方面,計算機語言類課程,作為計算機專業(yè)課程最基礎(chǔ)的課程,在教學(xué)中,由于開課一般先于其他專業(yè)課程,很難將其他專業(yè)課程的內(nèi)容與當前課程內(nèi)容相結(jié)合,容易陷入為教語言而教語言的境地。因此,采用何種方式,既能讓學(xué)生容易理解語言中的難點,又能突破語言教學(xué)本身的限制,這是計算機語言類課程教學(xué)所面臨的一個重大問題。
在教學(xué)準備過程中,我們對 C++語言的難點進行了深入地分析,發(fā)現(xiàn)這些內(nèi)容往往都有這樣的特點,即單純從 C++語言本身,很難甚至無法詮釋其技術(shù)原理,因此不引入新的知識,就無法讓學(xué)生了解這些技術(shù)的實現(xiàn)原理,做到不僅“知其然”,而且“知其所以然”。因此,在教學(xué)過程中,我們提出采用基于內(nèi)部視角的教學(xué)方法,在相關(guān)知識的教學(xué)過程中,引入了計算機內(nèi)部實現(xiàn)的技術(shù)細節(jié),在并不增加學(xué)生知識量的同時,通過說明技術(shù)的實現(xiàn)過程,使學(xué)生了解相關(guān)的技術(shù)原理,從而在掌握相關(guān)概念和方法的同時,加深對面向?qū)ο蠹夹g(shù)的了解和認識,突破語言教學(xué)本身所受的限制,為其他的相關(guān)專業(yè)課的學(xué)習(xí)打下較好的基礎(chǔ)。
所謂基于內(nèi)部視角的教學(xué)方法,是在計算機程序設(shè)計語言的教學(xué)過程中,適當?shù)匾氚▍R編、編譯、鏈接、調(diào)試和運行等相關(guān)技術(shù)實現(xiàn)的內(nèi)容,從而使學(xué)生能夠?qū)σ粋€程序從編輯到編譯,乃至運行等各個環(huán)節(jié)中,計算機內(nèi)部組織結(jié)構(gòu)和運行過程的方法,有一個正確的認識。
顯然,該方法對培養(yǎng)一名專業(yè)的程序員是十分有益的,這方面的內(nèi)容,也是一名專業(yè)程序員所必須具備的。但該教學(xué)方法在使用上還有著很大的不確定性,主要包括:
(1)程序設(shè)計語言本身的限制。由于不同的程序設(shè)計語言在計算機體系中所處的層次不同,因此,這一方法的實施有著本質(zhì)的不同。例如,象VB.Net、C#等語言,由于建立在.Net框架基礎(chǔ)之上,技術(shù)實現(xiàn)細節(jié)復(fù)雜,因此較難采用此方法;而對于匯編語言來說,內(nèi)存組織等相關(guān)技術(shù)內(nèi)容,則是實踐教學(xué)中的重要內(nèi)容。對于象 C和 C++這樣的中間語言來說,如何把握,則要根據(jù)教學(xué)內(nèi)容進行取舍;
(2)引入程度的把握。計算機內(nèi)部實現(xiàn)的技術(shù)細節(jié)有著先天的難度,實施中必須考慮學(xué)生的知識水平和結(jié)構(gòu),把握引入的程度。
我們認為,基于內(nèi)部視角的教學(xué)方法在以 C++為編程語言的面向?qū)ο蟪绦蛟O(shè)計教學(xué)中,應(yīng)該在如下方面引入:
(1)單純以 C++語言無法完美解釋的相關(guān)概念、技術(shù)等;
(2)作為學(xué)生選學(xué)的提高內(nèi)容;
(3)實踐教學(xué)環(huán)節(jié)的組成和補充。
在引入的內(nèi)容方面,應(yīng)遵循以下原則:引入的內(nèi)容對學(xué)生目前的認知水平和知識結(jié)構(gòu)來說,不會存在困難。
我們以若干實例來說明基于內(nèi)部視角的教學(xué)方法的應(yīng)用。
實例 1:繼承類與基類構(gòu)造函數(shù)的調(diào)用順序
在這一內(nèi)容方面,教材[1]認為,派生類對象的構(gòu)造函數(shù)調(diào)用順序是:基類構(gòu)造函數(shù)先調(diào)用,派生類函數(shù)后調(diào)用。并用如下程序的輸出來佐證。
//功能:演示繼承關(guān)系中基類與派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次序。
類似的程序也出現(xiàn)在文獻[2]和[3]中,而文獻[2]和文獻[3]也持同樣的觀點。但我們認為,這與構(gòu)造函數(shù)的調(diào)用原理是矛盾的,至少是不嚴謹?shù)?。問題在于:一個類的對象成員在初始化時,要調(diào)用該類的構(gòu)造函數(shù),而派生類對象作為該派生類的對象,在初始化時,怎么會先調(diào)用非該派生類的構(gòu)造函數(shù)呢?而且,這與繼承類的構(gòu)造函數(shù)的定義也相違背,因為基類構(gòu)造函數(shù)的參數(shù)是由繼承類的構(gòu)造函數(shù)傳遞而來的,若是基類的構(gòu)造函數(shù)先被調(diào)用,則所使用的參數(shù)從何而來?但單純地如此說明,沒有實驗的佐證,不能給學(xué)生以深刻的印象。
在教學(xué)中,我們演示了應(yīng)用Visual Studio 6的代碼跟蹤過程,來讓學(xué)生充分地了解這一點。在跟蹤過程中,打開匯編代碼的顯示開關(guān),在0x40109D處,清晰地看到繼承類的構(gòu)造函數(shù)被調(diào)用了,如圖 1所示,而在繼承類構(gòu)造函數(shù)調(diào)用過程中,基類的構(gòu)造函數(shù)被調(diào)用。
圖 1 構(gòu)造函數(shù)調(diào)用順序 (圖中黑行分別表示調(diào)用派生類和基類構(gòu)造函數(shù))
這樣,學(xué)生在觀察的基礎(chǔ)上能夠得到關(guān)于基類、派生類構(gòu)造函數(shù)正確的調(diào)用順序。進一步跟蹤還能夠發(fā)現(xiàn),雖然派生類對象構(gòu)造函數(shù)調(diào)用順序是先派生類再基類,但數(shù)據(jù)成員的初始化卻是按先基類再派生類的順序進行。因此,這一知識點可以用兩句話概括:派生類對象構(gòu)造函數(shù)調(diào)用順序是先派生類后基類,而數(shù)據(jù)成員初始化則是先基類成員后派生類成員。在明確了整個過程之后,學(xué)生可以認識到,單純依據(jù) cout的輸出來判斷構(gòu)造函數(shù)的調(diào)用順序是不可靠的。
采用同樣的方法,學(xué)生同樣能夠理解,C++程序中,代碼可以先于main函數(shù)執(zhí)行這一知識點。在這部分內(nèi)容的教學(xué)中,學(xué)生直觀地感受到語言代碼在計算機內(nèi)部的執(zhí)行過程,同時,對程序的調(diào)試又有了新的認識和方法。
實例2:虛函數(shù)的調(diào)用
虛函數(shù)是一塊較為難以理解的內(nèi)容,很多學(xué)生說到虛函數(shù)就說心里“發(fā)虛”,原因是用 C++語言本身的知識,很難解釋為什么指向基類對象的指針在指向派生類對象時,調(diào)用虛函數(shù)會進行動態(tài)綁定,而用對象直接調(diào)用虛函數(shù)卻不存在這一情況,這一現(xiàn)象與前面指向?qū)ο蟮闹羔樀闹R有著很大的不同。僅按書本的內(nèi)容,勢必只能讓學(xué)生了解這一現(xiàn)象,而不能讓學(xué)生真正了解多態(tài)性這一能體現(xiàn)OOP思想的典型現(xiàn)象中包含的實現(xiàn)方法,這對建立和培養(yǎng)基于 OOP對現(xiàn)實世界的實體進行抽象的思想是不利的。
在這一節(jié),我們在教學(xué)過程中,引入了虛函數(shù)表的知識,講明如果一個類有虛函數(shù),那么會在類中產(chǎn)生一個虛函數(shù)表,基類和派生類的同名虛函數(shù)在這個表中的位置是相同的,在調(diào)用虛函數(shù)時,程序是先查找這個虛函數(shù)表,然后根據(jù)表中的地址調(diào)用對應(yīng)的虛函數(shù)。當指針指向基類對象或指向派生類對象時,所使用的虛函數(shù)表是不同的,這樣,指針與虛函數(shù)表結(jié)合,從而實現(xiàn)了動態(tài)綁定這一運行時的多態(tài)性。在講授中,我們只引入了虛函數(shù)表,但對虛函數(shù)表在內(nèi)存中的位置,組織等則略過,這樣既讓學(xué)生掌握了原理,又不會因為繁瑣的細節(jié)而失去對整體知識的把握,從而影響教學(xué)效果。
在課后,我們對3個班的面向?qū)ο笳n程作了問卷調(diào)查,問卷的設(shè)計圍繞著基于內(nèi)部視角的教學(xué)方法展開。問卷發(fā)放 103份,總計收到有效問卷95份。在這些有效問卷中,有70.59%的學(xué)生認為,面向?qū)ο筮@門課在認識上存在著困難;有 39.2%的學(xué)生認為,困難的原因是內(nèi)容本身的難度,有51%的學(xué)生認為,內(nèi)容的難度是由“可以知其然,而難以知其所以然”造成的。從這個結(jié)果來看,引入適當?shù)膬?nèi)容,使得有難度的知識點得到合理的詮釋顯然是必要的,顯然,基于內(nèi)部視角的教學(xué)方法正切合了這一實際。調(diào)查情況也證實了這一點,有 88.02%的學(xué)生認為,引入內(nèi)部實現(xiàn)機制內(nèi)容對本門課程有很大的幫助,同時,還有 82.44%的學(xué)生認為,這樣的知識結(jié)構(gòu)對今后的職業(yè)生涯也有很大的幫助。
從上述調(diào)查結(jié)果可以看出,基于內(nèi)部視角的教學(xué)方法較為符合目前學(xué)生在面向?qū)ο蟪绦蛟O(shè)計這門課中的認知情況,符合學(xué)生在專業(yè)課中“想知其然并知其所以然”的認識能動性,并在較大程度上幫助學(xué)生更好地理解課程的內(nèi)容,同時,也開拓了學(xué)生的視野,能夠達到較為良好的教學(xué)效果。
本文提出了一種在面向?qū)ο蟪绦蛟O(shè)計教學(xué)中的基于內(nèi)部視角的教學(xué)方法,該方法主旨是在面向?qū)ο笳n程教學(xué)中,適當引入計算機內(nèi)部實現(xiàn)的內(nèi)容,從而能夠使學(xué)生了解面向?qū)ο笳Z言本身所難以詮釋的內(nèi)容,不僅讓學(xué)生能夠掌握相關(guān)課程內(nèi)容,還能夠了解相關(guān)技術(shù)實現(xiàn)機制,擴展了語言教學(xué)視野,從教學(xué)調(diào)查和實踐來看,起到了比較好的教學(xué)效果。
應(yīng)該看到,由于C++語言是基于中級語言C發(fā)展起來的,應(yīng)用內(nèi)部視角教學(xué)方法具有一定的優(yōu)勢,對于 java、C#等高級面向?qū)ο笳Z言,如何恰當?shù)貞?yīng)用該方法,則需要在今后的教學(xué)過程中加以探索。
[1]李師賢.面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ).高等教育出版社,2005.
[2]Stephen Prata.C++Primer Plus Fifth Edition.Macmillan Computer Pub,2005.
[3]Bruce Eckel.Thinking in C++ Second Edition.機械工業(yè)出版社,2002.
浙江理工大學(xué)重點課程建設(shè)項目(ZDKC0908)。