C++面向对象程序设计 学习心得:
这学期学了C++面向对象程序设计,通过成绩单处理,ATM,通讯录,图书管理系统这几个简单系统,慢慢地对系统的设计有了一个初步的认识。
简单说一下设计系统具体的过程以及一些注意事项:
拿到一个设计的题目或者说一个项目的需求分析,首先要根据大体功能(需求分析)规划出基本的思路框架,然后一步步去思考实现,逐步地去优化,顺序可以从管理端到用户端,登录之类的可以放到最后写。(对于大体功能或者说需求分析,我总觉得这是设计系统最重要的一步,个人总是喜欢先列出来,比如先在纸上演示出来,然后弄成Word文档理清系统的具体框架,然后在写程序的时候作为参考,我觉得会让思路变得清晰,具体的可以参考下面的一段。)
图书管理系统
管理端:
数据类:
书籍信息(类向量):
{
出版信息(出版社,出版时间(结构体)),书名,作者,索书号,馆藏册数(总数目,可借书目),每本书的借阅信息(何时借,何时还)
}
读者信息(类向量):
{
每个借阅用户的用户名,读者的编号(或学号等其他信息),已借阅书的数目,以及已借书的信息(何时借,何时还等)
}
借阅记录(类向量):
{
每借一本书新增一个借阅记录(包括借的书的书籍信息,以及借书人的用户信息,以及结束日期与应还日期等)
}
操作类:
书籍信息(类向量),读者信息(类向量),借阅记录(类向量)
几次查询就要匹配几组map(删除某项信息后要重新构建新map)
新增图书,用户操作
查询与修改(删除)书籍信息:(可按书名,索书号等查询)查询到该书后显示借阅信息,书籍信息,然后可执行修改操作(书的数目等)
查询与修改(删除)用户信息:(可按用户名,读者编号等查询)查询到该用户后显示用户信息,该用户的借阅信息,并可对用户信息执行修改删除等操作
用户端:
数据类:
个人信息情况(与管理端相一致),另外有个人的借阅信息,借阅记录(所借书名等,何时借何时还等信息,以是否续借等)
操作类:
查询书籍信息(只限查询,不允许修改或删除图书信息),然后可以选择借阅(根据是否存在库存以及自身是否可借(是否达到最大借书额度或是否超期(超期后是否缴纳相应罚款))等信息进行操作)
查询自身借阅信息(已借书籍信息(包括书籍自身信息及借书日期与应还日期以及是否续借等),是否达到最大借书额度(还可借阅几本)等)
登录(合并管理端与用户端):
输入账号密码:if账号密码为管理端则进入管理端系统,else if账号密码为用户端则进入用户端系统,else账号或密码输入错误,请重试
大体框架思路有了以后根据功能实现去设计数据结构,即数据的储存方式,例如查询方式根据查询功能需要设置多少组map或我们使用向量时是否要考虑使用下标去访问等,数据的存储往往根据我们要实现的功能去变换。另外数据的存储与操作方式还会影响程序的效率,是值得思考与关注的一点。
数据有了,我们就要进行数据的导入与保存,这时我们通常会采用重载输入输出,这是很严格的一个过程,必须保证数据与重载完全对应起来,否则可能无法导入数据,那这个程序就宣布作废了,一个没有数据、无法对数据进行操作的程序是没有意义的。很多时候重载会给我们带来很多便利,比如我们对时间类进行重载,作出时间差或者根据特定的值去推算时间等。但是又不得不说重载还是尽量少用一些, 因为有的时候万一错了可能会导致大的问题,比如上面提到的文件导入与保存。
另外重要的一点是继承中基类与派生类之间的关系,继承虽然好用,利于减少代码量,增强可读性,加强代码之间的联系等,但是稍有不慎就会出现错误,继承出现的错误有的时候可并非容易找,毕竟这是继承的特性,例如基类中save函数与析构函数之间的关系没有把握好,就会产生操作失败的问题,因为派生类操作完毕后进行了一次保存,但是基类析构时这时若再调用save函数,保存的是基类中未修改的数据,直接覆盖掉了之前的数据,相当于没有执行操作。当然这是继承中需要注意的问题,可能很多时候我们都知道这是错的,但是用到程序中数据一多就混乱了,这需要我们长期练习才行啊。
另外对于继承的设计,可能有很多的方式,以图书馆查询功能为例:
一、有的同学是所有的功能写到一起,组成一个功能大类,然后用管理端与用户端分别继承,然后调用各自的功能。
二、有的同学是把对书籍的所有操作写成一个类,然后管理端与用户端分别继承各自的操作
三、是老师说的那种单独写一个查询书籍的类,然后两端只继承这个查询功能。
然后我觉得各有好处:
第一种比较省事,思路也比较特殊,但是好像又不紧凑,容易出错。
第二种的意思是所有的书籍文件导入该基类中,然后派生类就不用再写书籍类的向量了,派生类直接在基类的基础上通过调用基类函数直接对基类进行对书籍的增删查改(管理端),借书还书续借(用户端)等一系列操作。有点像第一种,但是第一种连对用户的操作一起包含进去了。
第三种就是单独列出一个类导入文件进行查询,不过这在定义对象时管理端或者用户端对象已经导入了书籍文件,造成了重复。
其实前两种来看都是可以的,还可以利用基类定义protected成员减少派生类的导入过程,使其操作直接执行在基类中,这也是一种很好的办法。
对于不同的端口,我们所能进行的访问与操作不同,这时我们可以考虑使用多态与虚函数,当然,我们也可以进行“多态”去代替,假多态的实现方式可以是这样:登录上进行对对象进行单独定义:登录管理端定义管理端对象,用户端定义用户端对象,然后分别进行各自的函数调用实现功能。对于多态来讲,我们可以定义抽象类基类(纯虚函数),然后分别在不同的端口进行各自的定义从而实现多态。这也是在继承关系选择时就要考虑的一部分。
最后要说的很重要的一步是程序的调试:我们都不是天才,不可能一步写完所有程序直接运行通过,我们做系统的数据量太大,必须一个功能点进行一步调试,这样才不至于到最后写了一堆没有办法下手改的程序,如果我们哪一步没弄好就不要往下进行,因为这样容易出现连环的错误。我们刚刚对系统有一个初步了解,一定要多练习调程序,按步骤找错误,看具体是哪个函数有问题,慢慢改,慢慢来,到最后保证程序连续起来不会出问题。其实我觉得进步最快的时候就是调程序改代码,我们刚开始做,不怕错的多,相反这是件好事,会给我们以后调程序打下更坚实的基础。我们也可以尝试去帮同学调程序,这其实是一种乐趣,会体会到别人对于同一个问题不同的思路,会看到对于细节的处理的不同方式,当然这不是叫我们去抄袭,去帮别人写系统(在自己的程序没有进行完之前不要去参考别人的代码,不要去看网上的资料,要学会独立思考,将自己的思路写到代码里面,我觉得这才是我们能学到东西的前提)调程序这只是自我提升的一种途径,有的时候自己错的多了,看别人的程序就能一眼看出来别人的错误,看起来挺厉害的,其实这个过程挺心酸的,这不就是自己之前错的那些吗。
按照上面的思路来,一个简单的系统基本就可以做出来了,但是我们离社会对我们的要求还很远很远,不过我们已经大体掌握了设计系统的基本思路,接下来我们可以自己深入了解一些东西了。当然我们也不能急于求成,很多东西我们都要反复练习,一定要把基础打实。师傅领进门,修行看个人,接下来要努力学习更加深入的知识啊,同时希望能在毕业时给自己的大学生活交一份满意的答卷。
道阻且长,当加倍努力,加油!