李涛,任廷艳,罗刚,黎路
(黔南民族师范学院,都匀 558000)
多态性是面向对象编程语言的基本特征之一,它是指一个类的成员函数在程序运行时具有多种形态[1]。在C++语言中,通常使用虚函数形式来实现的[2],其核心理念通过基类指针或者引用来指向子类对象,并调用由子类重写的个性化的虚函数[3]。但从实际教学效果来看,由于面向对象编程思想抽象化,对于初学者来说很难理解这些抽象的概念以及虚函数运行时调用机制[4],导致学生无法对面向对象的多态性特征深入理解。
针对问题,从面向对象的程序设计思想出发,尝试将设计模式的一些思想引入到课程教学中。让学生通过案例学习,加深学生理解虚函数实现运行多态性的基本原理[5]。教学实践表明,在教学过程中运用设计模式相关内容可加深学生对面向对象编程思想的理解,以提高他们解决问题的实践能力。
在教学过程中,我们提出了一种启发式的教学方法,针对教学内容选择设计模式中部分思想进行辅助教学,将原先注重讲解语法的教学模式,转化为引入精心设计教学案例,通过案例逐步引导学生完成相关的类和功能设计。在完成设计的基础上,引导学生对其设计代码进行分析、比较和优化。在此过程中,通过教师分析与讲解,学生回答问题及讨论,让学生加深对继承、多态、虚函数等概念的理解,最后,引导学生完成相应的编码,并让其做相应总结。这样大大提高了学生举一反三的能力,对于编程的能力也有很大提升[6]。
以面向对象中多态性教学为例,通过引入设计模式中的模板方法模式让学生了解抽象类和纯虚函数的概念及用途。
(1)引入案例:教学过程中引入主题场景:从键盘输入一个整型数组,对数组中的数由小到大进行排序,然后把排序之后的结果打印显示出来。任务整个流程由输入数据、排序和打印数据三个具体步骤组成,输入数据和打印数据两个步骤是整个流程中不变的,而对数据进行排序这一步骤,因可以选择不同排序算法,存在可变性造成实现细节不同。
(2)提出问题:遵循面向对象思想完成相关类定义及功能实现?在讨论中,学生会指出定义一个类,将输入数据和打印数据以成员函数的形式实现,同时定义两个用于排序成员函数(简单选择排序和冒泡排序)。然后通过定义类的对象按步骤顺序依次调用输入、排序及打印相应的成员函数来实现整个程序。学生设计部分程序示例代码如下。
#include
#include
using namespace std;
class AbstractSort
{
public:void inputData();//输入数据void print();//打印数据
void SelectSort();//简单选择排序void BubbleSort();//冒泡排序
private:
int array[6];
};
int main()
{
AbstractSort arraysort;
arraysort.inputData();
arraysort.SelectSort();
arraysort.print();
return 0;
}
这段程序代码初步实现整个流程,但是基于面向对象的,不能体现面向对象的多态性。多态使程序调用的函数在运行时动态确定,而不是在编译时静态地确定[7]。某个任务要实现的算法需要多个步骤,但其中有一些步骤是固定不变的,而另一些步骤则是不固定的,而设计模式中模板方法模式就是应用于在这种场景下。首先在抽象类中确定整个流程的步骤顺序,其次实现固定不变的步骤,最后把变化或不固定的步骤留给子类来实现。
(3)模式引入:模板方法模式使得子类可以不改变算法的结构即可重新定义该算法的某些特定步骤[8],是由一个抽象类和一组子类通过继承结构组成。在抽象类中的定义一个模板方法,它是把基本操作方法组合在一起形成一个总算法或一个总行为的方法,并由子类不加以修改地完全继承下来[9],通常定义为成员函数。将算法中不变步骤以类成员函数形式实现,算法中的变化步骤或一些不确定的细节以纯虚函数的形式在子类中实现。纯虚函数是实现一个接口来规范派生类的行为,也就是说,规范继承抽象类必须实现该函数。
设计类图如图1。
图1 模板方法模式下的类图
(4)实现:设计一个描述数组排序的抽象类AbstractSort,定义成员函数inputData用于输入数据,因存在不同排序算法,把成员函数Sort设置为纯虚函数,具体由子类来实现使用哪种排算法进行排序。定义print成员函数作为模板方法,作为整个步骤序列总控制,依次调用inputData和Sort等成员函数。定义两个子类,BubbleSort和SelectSort,分别继承抽象类AbstractSort,并对sort函数进行定义实现不同排序算法。下面给出抽象类AbstractSort和BubbleSort子类代码如下:
class AbstractSort{
public:
virtual void sort(int array[],int n)=0;//设置sort()作为纯虚函数
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<<"输入数据"< inputData(array,n); sort(array,n); cout<<"排序结果:
"; for(int i=0;i cout< } }; class BubbleSort:public AbstractSort{ public: void sort(int array[],int 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)总结:抽象类是一种特殊的类,是为了抽象和设计的目的建立的,主要功能是将相关操作组织为继承层次结构中的结果接口,继承层次结构为派生类提供公共根。派生类将在其基类中具体实现作为接口的操作。纯虚函数是在抽象类中声明的一个虚函数,它要求任何派生类定义自己的实现方法以实现多态性。模板方法模式主要应用于多个子类中有共有的代码,并且逻辑基本相同[10];对一些复杂的算法进行了分割,将算法的固定部分设计为模板方法和父类的成员函数,而一些可变的细节则由其子类实现。 在C++课程教学中引入部分设计模式的思想进行授课,不仅是对传统C++课程的革新,更是提高学生实践能力的有效手段。在实践中发现,设计模式对于塑造学生的编程思维,培养学生的编程习惯,提升学生的编程水平具有重要作用。3 结语