《C++面向对象程序设计》课程中

“封装”性概念自学指导设计

李维田

摘 要:本文通过对《C++面向对象程序设计》课程中的难点问题“封装”性的自学指导进行设计的过程,探索指导理工科开放教育学员通过“引入概念、用实例巩固概念、通过总结加深概念”的自学方法。本设计尚处于不断完善中,可以给探讨同类自学指导的设计者提供一个借鉴。

关键词:开放教育 自学指导 面向对象程序设计 封装性

“封装”性概念是中央电大开放教育“计算机科学与技术专业”必修课《C++面向对象程序设计》中重点与难点内容之一。理解了“封装性”概念,可以加深对面向对象程序设计思想理解,进一步掌握C++程序设计语言中“类”、“对象”、“友元”等概念。

一、问题的提出

在几年从事开放教育《C++面向对象程序设计》课程的教学中发现,开放教育本科同学对“封装”性概念理解较难。究其原因是由于他们在过去所接受的教育中已经习惯了面向过程的程序设计思想,例如部分同学学习过汇编语言、C、Pascal或者basic语言,有的同学还能使用诸如Foxbase、Foxpro等数据库管理系统开发一些简单的应用程序等所致。为了分解学习中的难点,便于学生的自主学习,设计了对“封装性”概念的自主学习指导。

二、“封装”性概念自学指导设计的任务

学生自主学习成功的关键是在导师的导读指引下,按本课程的实施细则中自学计划认真自学。自学指导设计的任务是采用一种可以便于同学们自学、融会贯通本部分知识的方法,使同学们理解和掌握这一部分知识。

1、“封装”性概念的自学目标

理解封装性是面向对象方法中的一种重要特征;

辨清对象的私有成员与封装;

理解友元的作用与封装

2、“封装”性的自学过程

复习已经学习过的相关知识,从中提炼“封装”性实例;

通过具体范例程序体会“封装”性概念;

总结与提高。

三、设计过程

1、引入概念

“封装”性概念是在第九章“面向对象程序方法”中提出,在后续章节中使用的。

自学中首先要理解封装性是将基本数据和对此数据进行操作的过程和函数结合起来,可以保证各软件部件具有良好的模块性的基础(对象)——即其包装性;其次是这个模块性基础将尽可能对外界公布一个有限的界面,而将其细节隐藏起来,与其他对象的交往通过这个界面进行——信息隐藏性。

通过生活实例理解“封装性”概念。

一个公司(或企业)的经营活动可以理解为一个“封装性”的概念。该公司的基本活动可以由其各部门(基本数据)和调度部门(对此数据操作的过程)或共同完成的产品(函数)结合起来。各部门之间的(外界)联系是由公司总调度(或领导)和各部门调度(或部门领导)实现的。

加深概念理解,对“封装”性概念要从三个方面理解。

⑴所有软件的内部都应有明确的范围,清楚的外部边界;这就象公司的各部门有明确的职责范围、各部门之间有确定的权限界限。

⑵每个软件部件都应具有友好的界面或接口,以表明软件部件之间的相互作用和相互联系;这就象公司的各部门相互间的衔接工序及各部门之间有联系与制约。

⑶完成、保护和隐藏软件的内部实现,用户不必了解其具体的实现;这就像一个工厂的各个车间生产不同的零部件,本车间完成自己的工作,对外提供成品零部件,使用零部件者不必知道其生产过程。

理解“封装”性的好处。

有了封装性,软件设计人员可以集中精力考虑开发系统各模块之间的关系等重大问题,而模块内部的实现可得到程序设计人员的研究与完善,可以充分保证模块质量和可靠性,也支持软件工程化思想。

2、通过实例巩固概念通过总结加深概念

在教材的第十章“类与对象”中是封装性的具体体现。在这里我们可以看到对象通过类来定义。也就是说,类是进行封装和数据隐藏的工具,进行数据和方法封装的基本逻辑单位。类中可以定义公有成员、保护成员和私有成员。公有成员可被任何函数访问;保护成员可被该类的成员函数和相应的友元函数引用;而私有成员则只能为相应类的成员函数和相应的友元函数引用。引入私有成员封装性和友元封装性的实例:

⑴通过对象的私有成员实例理解封装

#include

class personnel

{ public:

personnel (int mon)

{ money=mon;

}

void get_salary (personnel &p,int mon)

{ p.money-+mon;

money +=mon;

}

int get_mon ()

{ return money;

}

private:

int money; //私有成员

};

void main() {

personnel boss(1000); // 创建boss 时付给其1000元

personnel employee(0);

cout<<”Before get_salary,boss:”<
<<”employee:”<
employee.get_salary(boss,200); // employee从boss领取200元

cout<<”After get_salary,boss:”<
<<”employee:”<
}

运行结果:

Before get_salary,boss: 1000 employee: 0

After get_salary,boss: 800 employee: 200

通过这个实例我们看到:在程序中定义了一个表示公司所有职员的personnel类,其中的成员函数get_salary (personnel &p,int mon)可以改变私有成员money。在主函数中,首先在创建boss 时付给其1000元,employee从boss领取200元,即执行employee.get_salary(boss,200)之后,employee的money增加了200元;而boss的money减少了200元。Employee通过成员函数操作改变了boss的money。

上述实例告诉我们:程序编译过程中,编译器认为通过personnel &p的声明,p本身已经属于personnel 类,在get_salary (personnel &p,int mon)中直接操作其私有数据成员属合法操作,如果有非成员函数对其进行操作就属于非法了。

⑵通过友元的实例理解封装

#include

#include

class point //定义一个类

{ public:

point (float xi,float yi)

{ X=xi,Y=yi;

}

float Get_X() {return X;}

float Get_Y() {return Y;}

friend float distance (point &a,point &b); //声明为类的友元

private:

float X,Y; //类的私有成员

};

float distance (point &a,point &b)

{

float dx = a.X-b.X; //因为是友元函数而访问类的私有成员X

float dy = a.Y-b.Y; //因为是友元函数而访问类的私有成员Y

return sqrt (dx*dx+dy*dy);

}

void main() {

point p1(3.0,5.0),p2(4.0,6.0); //创建类的对象

float d = distance (p1,p2); //通过友元函数访问类的私有成员

cout <<”The distance is:”<
}

运行结果:

The distance is:1.41421

在上面的例子中,我们看到只使用了float d = distance (p1,p2)就完成了对point类的对象p1和p2的访问。如果不采用友元,主函数应该增加:

float dx = p1.Get_X()-p2.Get_X();

float dy = p1.Get_Y()-p2.Get_Y();

float distance = sqrt(dx*dx+dy*dy);

才能完成上述程序的功能。由此可见引入友元后可以简化程序设计者的烦琐工作。

3、通过总结加深概念

当同学们按照上述两步完成自学后,应当根据自己的体会进行总结。下面是引导性总结提纲:

⑴在C++面向对象程序设计语言中封装单元是什么?(类型)

⑵判断多个对象是否属于同一类的依据是什么?(是否符合相同的类型系统)

⑶程序中相同类的不同实例对象之间是否可以互访对方的私有成员?(可以——例1)

⑷引入友元的优点是什么?(节省成员函数调用的开销,提高程序效率——例2)

⑸类的设计者是否必须在考虑好该类的各种可能的使用情况后才能开始设计该类,为什么?(不必,类的使用者可以根据具体要求通过友元增加类的接口)

⑹使用友元要注意什么问题?(引入友元是人为地破坏了对象间的松耦合关系,削弱C++的封装和数据隐藏,可能导致程序的可维护性和可读性较差,必须引起足够重视)

本自学指导以Word文档方式在设计者的公开邮件箱里提供给开放教育试点“计算机科学与技术”专业2000、2001级部分同学,对指导自学起到了一定的作用。但对封装在其他方面的体现还有待于进一步的研究与设计。

作者简介:李维田,沈阳电大机电工程系,副教授。

回目录

上一篇 C++运算符重载探讨

下一篇C++ 继承性应用实例—日期和时间

 

S