李濤,任廷艷,羅剛,黎路
(黔南民族師范學(xué)院,都勻 558000)
多態(tài)性是面向?qū)ο缶幊陶Z言的基本特征之一,它是指一個類的成員函數(shù)在程序運(yùn)行時具有多種形態(tài)[1]。在C++語言中,通常使用虛函數(shù)形式來實現(xiàn)的[2],其核心理念通過基類指針或者引用來指向子類對象,并調(diào)用由子類重寫的個性化的虛函數(shù)[3]。但從實際教學(xué)效果來看,由于面向?qū)ο缶幊趟枷氤橄蠡?,對于初學(xué)者來說很難理解這些抽象的概念以及虛函數(shù)運(yùn)行時調(diào)用機(jī)制[4],導(dǎo)致學(xué)生無法對面向?qū)ο蟮亩鄳B(tài)性特征深入理解。
針對問題,從面向?qū)ο蟮某绦蛟O(shè)計思想出發(fā),嘗試將設(shè)計模式的一些思想引入到課程教學(xué)中。讓學(xué)生通過案例學(xué)習(xí),加深學(xué)生理解虛函數(shù)實現(xiàn)運(yùn)行多態(tài)性的基本原理[5]。教學(xué)實踐表明,在教學(xué)過程中運(yùn)用設(shè)計模式相關(guān)內(nèi)容可加深學(xué)生對面向?qū)ο缶幊趟枷氲睦斫?,以提高他們解決問題的實踐能力。
在教學(xué)過程中,我們提出了一種啟發(fā)式的教學(xué)方法,針對教學(xué)內(nèi)容選擇設(shè)計模式中部分思想進(jìn)行輔助教學(xué),將原先注重講解語法的教學(xué)模式,轉(zhuǎn)化為引入精心設(shè)計教學(xué)案例,通過案例逐步引導(dǎo)學(xué)生完成相關(guān)的類和功能設(shè)計。在完成設(shè)計的基礎(chǔ)上,引導(dǎo)學(xué)生對其設(shè)計代碼進(jìn)行分析、比較和優(yōu)化。在此過程中,通過教師分析與講解,學(xué)生回答問題及討論,讓學(xué)生加深對繼承、多態(tài)、虛函數(shù)等概念的理解,最后,引導(dǎo)學(xué)生完成相應(yīng)的編碼,并讓其做相應(yīng)總結(jié)。這樣大大提高了學(xué)生舉一反三的能力,對于編程的能力也有很大提升[6]。
以面向?qū)ο笾卸鄳B(tài)性教學(xué)為例,通過引入設(shè)計模式中的模板方法模式讓學(xué)生了解抽象類和純虛函數(shù)的概念及用途。
(1)引入案例:教學(xué)過程中引入主題場景:從鍵盤輸入一個整型數(shù)組,對數(shù)組中的數(shù)由小到大進(jìn)行排序,然后把排序之后的結(jié)果打印顯示出來。任務(wù)整個流程由輸入數(shù)據(jù)、排序和打印數(shù)據(jù)三個具體步驟組成,輸入數(shù)據(jù)和打印數(shù)據(jù)兩個步驟是整個流程中不變的,而對數(shù)據(jù)進(jìn)行排序這一步驟,因可以選擇不同排序算法,存在可變性造成實現(xiàn)細(xì)節(jié)不同。
(2)提出問題:遵循面向?qū)ο笏枷胪瓿上嚓P(guān)類定義及功能實現(xiàn)?在討論中,學(xué)生會指出定義一個類,將輸入數(shù)據(jù)和打印數(shù)據(jù)以成員函數(shù)的形式實現(xiàn),同時定義兩個用于排序成員函數(shù)(簡單選擇排序和冒泡排序)。然后通過定義類的對象按步驟順序依次調(diào)用輸入、排序及打印相應(yīng)的成員函數(shù)來實現(xiàn)整個程序。學(xué)生設(shè)計部分程序示例代碼如下。
#include
#include
using namespace std;
class AbstractSort
{
public:void inputData();//輸入數(shù)據(jù)void print();//打印數(shù)據(jù)
void SelectSort();//簡單選擇排序void BubbleSort();//冒泡排序
private:
int array[6];
};
int main()
{
AbstractSort arraysort;
arraysort.inputData();
arraysort.SelectSort();
arraysort.print();
return 0;
}
這段程序代碼初步實現(xiàn)整個流程,但是基于面向?qū)ο蟮?,不能體現(xiàn)面向?qū)ο蟮亩鄳B(tài)性。多態(tài)使程序調(diào)用的函數(shù)在運(yùn)行時動態(tài)確定,而不是在編譯時靜態(tài)地確定[7]。某個任務(wù)要實現(xiàn)的算法需要多個步驟,但其中有一些步驟是固定不變的,而另一些步驟則是不固定的,而設(shè)計模式中模板方法模式就是應(yīng)用于在這種場景下。首先在抽象類中確定整個流程的步驟順序,其次實現(xiàn)固定不變的步驟,最后把變化或不固定的步驟留給子類來實現(xiàn)。
(3)模式引入:模板方法模式使得子類可以不改變算法的結(jié)構(gòu)即可重新定義該算法的某些特定步驟[8],是由一個抽象類和一組子類通過繼承結(jié)構(gòu)組成。在抽象類中的定義一個模板方法,它是把基本操作方法組合在一起形成一個總算法或一個總行為的方法,并由子類不加以修改地完全繼承下來[9],通常定義為成員函數(shù)。將算法中不變步驟以類成員函數(shù)形式實現(xiàn),算法中的變化步驟或一些不確定的細(xì)節(jié)以純虛函數(shù)的形式在子類中實現(xiàn)。純虛函數(shù)是實現(xiàn)一個接口來規(guī)范派生類的行為,也就是說,規(guī)范繼承抽象類必須實現(xiàn)該函數(shù)。
設(shè)計類圖如圖1。
圖1 模板方法模式下的類圖
(4)實現(xiàn):設(shè)計一個描述數(shù)組排序的抽象類AbstractSort,定義成員函數(shù)inputData用于輸入數(shù)據(jù),因存在不同排序算法,把成員函數(shù)Sort設(shè)置為純虛函數(shù),具體由子類來實現(xiàn)使用哪種排算法進(jìn)行排序。定義print成員函數(shù)作為模板方法,作為整個步驟序列總控制,依次調(diào)用inputData和Sort等成員函數(shù)。定義兩個子類,BubbleSort和SelectSort,分別繼承抽象類AbstractSort,并對sort函數(shù)進(jìn)行定義實現(xiàn)不同排序算法。下面給出抽象類AbstractSort和BubbleSort子類代碼如下:
class AbstractSort{
public:
virtual void sort(int array[],int n)=0;//設(shè)置sort()作為純虛函數(shù)
void inputData(int array[],int n){
int i;
for(i=0;i cout<<"array["< cin>>array[i]; cout< } } void print(int array[],int n){//作為模板方法控制整個流程步驟順序 cout<<"輸入數(shù)據(jù)"< inputData(array,n); sort(array,n); cout<<"排序結(jié)果:
"; for(int i=0;i cout< } }; class BubbleSort:public AbstractSort{ public: void sort(int array[],int n){//純虛函數(shù)的實現(xiàn)由派生類給出 int i,j,temp; for(i=0;i for(j=0;j if(array[j]>array[j+1]){ temp=array[j]; array[j]=array[j+1]; array[j+1]=temp; } } } } }; 測試程序如下: int main(){ int a[5]; AbstractSort*p; SelectSort cs; p=&cs; p->print(a,5); int b[8]; BubbleSort bs; p=&bs; p->print(b,8); return 0; } (5)總結(jié):抽象類是一種特殊的類,是為了抽象和設(shè)計的目的建立的,主要功能是將相關(guān)操作組織為繼承層次結(jié)構(gòu)中的結(jié)果接口,繼承層次結(jié)構(gòu)為派生類提供公共根。派生類將在其基類中具體實現(xiàn)作為接口的操作。純虛函數(shù)是在抽象類中聲明的一個虛函數(shù),它要求任何派生類定義自己的實現(xiàn)方法以實現(xiàn)多態(tài)性。模板方法模式主要應(yīng)用于多個子類中有共有的代碼,并且邏輯基本相同[10];對一些復(fù)雜的算法進(jìn)行了分割,將算法的固定部分設(shè)計為模板方法和父類的成員函數(shù),而一些可變的細(xì)節(jié)則由其子類實現(xiàn)。 在C++課程教學(xué)中引入部分設(shè)計模式的思想進(jìn)行授課,不僅是對傳統(tǒng)C++課程的革新,更是提高學(xué)生實踐能力的有效手段。在實踐中發(fā)現(xiàn),設(shè)計模式對于塑造學(xué)生的編程思維,培養(yǎng)學(xué)生的編程習(xí)慣,提升學(xué)生的編程水平具有重要作用。3 結(jié)語