免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 无风之谷
打印 上一主题 下一主题

让我欢喜让我忧——我的C++之路 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
951 [报告]
发表于 2012-04-23 13:46 |只看该作者
回复 951# 幻の上帝

终结这个话题好不好……    呃,与你讨论的内容没有关系,不是批评那些内容……  而是地点不合适……
前面只是和walle开个玩笑……  让他消消气而已……
继续歪楼不好不好……

论坛徽章:
0
952 [报告]
发表于 2012-04-23 14:01 |只看该作者
幻の上帝 发表于 2012-04-23 13:45
回复 928# 陈良乔

= =

确实没有在Google中求证
iciba给出这个词,我就直接用了,没有太多考虑

是我太疏忽了,谢谢你

论坛徽章:
0
953 [报告]
发表于 2012-04-23 14:13 |只看该作者
继续后面的章节吧
第三部分,类与对象
因为原文文档是修订状态,有点乱,各位包涵一下

  
图6-13  对象及对象之间的关系
6.4.32  分析对象的属性和行为
在找到对象之后,就可以分析这些对象所拥有的属性和行为,利用面向对象的封装的机制将其封装成具体的类。首先,分析这个问题中最基础的员工类对象Employee。根据老板的要求(在实际开发中,来自于客户的需求)问题描述,为了找到工资最高的员工,我们必须记录每个员工的姓名(m_strName);为了根据在职时间(现在时间减去入职时间)动态地计算员工的工资,我们必须记录员工的入职时间(m_nYear)。我们需要输入员工的姓名和入职时间,所以这个对象必需的属性就是姓名和入职时间。
分析了员工类Employee的属性,那么它又该拥有什么样的行为呢?类的行为都是用来完成需求分析中的用例的,所以,Employee类的行为跟它要完成的用例密切相关。为了完成“计算最大值”用例,它应该有一个计算工资的行为(GetSalary()),可以根据员工的在职时间动态地计算员工的工资。但是,Employee类作为具体的员工类Officer和Staff的基类,并不知道工资的具体计算方法,所以这个行为只是一个接口而已,需要留待它的派生类来具体实现;而要计算工资,它又必须知道员工的在职时间,所以它还必须有一个获得在职时间的行为(GetWorkTime);同时,为了完成“查询工资”这个用例,程序需要知道员工的姓名,所以员工类应该提供一个获得名字的行为(GetName());在最后,为了完成“输出数据到文件”的用例,Employee类还必须提供获得员工级别(GetLevel())和入职年份(GetYear())的行为,从而可以获取员工的信息并将其输出。
经过这样的分析,小陈得出了员工类Employee应该具备的属性和行为。为了记录自己的分析结果,让结果一目了然,小陈将分析结果画成了UML类图:

Employee类的属性和行为
具体的员工类Officer和Staff是Employee的派生类,在Employee类的基础上,这两个具体的员工类并没有额外的需要描述的内容,所以它们不需要新添加属性,只需要从基类继承已有的属性即可。而至于行为,具体的员工类需要负责具体的工资计算和返回不同的级别,所以它们需要实现基类中的GetSalary()和GetLevel()这两个虚函数。经过这样的分析,Officer和Staff类应该具备的属性和方法就很清楚了。小陈将它们用如下的UML类图来表示:

Officer和Staff类的属性和行为。
按照同样的方法,小陈接着分析用于管理这些员工对象的SalarySys类。为了保存和管理多个Employee对象,SalarySys类必须有一个数组来保存这些对象,而为了应用面向对象的多态机制来动态地计算员工工资,数组中保存的不应该是这些对象本身,而应该是指向这些对象的指针;同时,数组只是表示了SalarySys所能够保存的最多的对象指针,但是并不是每个指针都是有效的,我们还必须用一个属性来表示当前有效的指针的个数(m_nCount);另外,SalarySys需要将从文件读取数据,最后还需要将数据写入文件,所以它还需要一个记录数据文件名的属性(m_strFileName)。
在SalarySys类的行为上,小陈还是同样从它要完成的用例来分析。根据小陈之前对这个程序进行的简单需求分析,它首先需要完成“输入数据”这个用例,而这个用例又包含了“从文件读取”和“手工输入”这两个用例,这就要求SalarySys类应该具有从文件读取数据(Read())和让用户手工输入的行为(Input());完成“输入数据”之后,就是“处理数据”,它也同样包括了“计算最大值”和“查询工资”两个用例,这就要求SalarySys类具有查找所有工资数据中的最大值(GetMax())和根据用户输入的姓名查询相应工资信息(Find())的行为;最后,就是“输出数据”这个用例,它要求SalarySys具有将所有工资数据保存到数据文件(Write())的行为。
分析完成之后,小陈同样将分析结果绘制成了UML类图:

SalarySys类的属性和行为
同时,工资管理系统要显示所有员工的信息,这也就是员工对象必须对外提供公有接口以便外界能够获得它的姓名和入职时间属性。其次,根据员工级别的不同,员工被分成经理和普通员工两类,根据面向对象中继承的思想,为了复用基类的设计和代码,我们让这两个类从基类中派生,从而直接拥有基类的属性和行为。但是,在问题描述中,经理和普通员工这两个对象的工资计算方式是不同的,所以这里可以利用面向对象的多态机制对基类中的行为进行重新定义。通过这样的分析,我们就清楚了对象的属性和行为,利用面向对象的多态机制将这些属性和行为封装起来,就形成了具体的类,如图6-14所示。

图6-14  员工类的属性和行为

图6-14  员工类的属性和行为

图6-15  工资管理系统类的属性和行为
完成了员工相关类的创建后,我们来看看对员工对象进行管理的工资管理系统,分析它应该具有哪些属性和行为。根据问题描述,工资管理系统要对所有输入的员工对象进行管理,所以它必须有一个属性来保存它所管理的所有员工并且有一个属性用来记录当前的员工总数。因为要管理多个员工对象,所以可以使用数组作为其保存员工对象的属性。为了处理问题描述中的事务,例如员工信息的输入和显示及计算平均工资等,它必须具备相应的行为,也就是它必须提供相应的成员函数供外界调用以完成相应的事务。经过这样的分析,工资管理系统类实现如图6-15所示。
面向对象分析方法
这里只是利用面向对象思想对一个小问题进行了分析。当利用面向对象思想设计开发比较大的系统时,过程当然不会这么简单。实际上,面向对象开发方法的研究已日趋成熟,国际上已有不少面向对象开发的方法出现。
1.  Booch方法
Booch方法最先描述了面向对象软件开发方法的基础问题,指出面向对象开发是一种不同于传统的功能分解的设计方法。面向对象的软件分解更接近人对客观事务的理解,而功能分解只能通过问题空间的转换来获得。
2.  Coad方法
Coad方法是由Coad和Yourdon于1989年提出的面向对象开发方法。该方法的主要优点是通过多年来大系统开发的经验与面向对象概念的有机结合,在对象、结构、属性和操作的认定方面,提出的一套系统的原则。该方法完成了从需求角度来进一步进行类和类层次结构的认定。尽管Coad方法没有引入类和类层次结构的术语,但事实上已经在分类结构、属性、操作、消息关联等概念中体现了类和类层次结构的特征。
3.  OMT方法
OMT方法是由James Rumbaugh等5人于1991年提出来的。该方法是一种新兴的面向对象的开发方法,开发工作的基础是对现实世界的对象建模,并围绕这些对象使用分析模型来进行独立于语言的设计。面向对象的建模和设计促进了对需求的理解,有利于开发更清晰、更易维护的软件系统。该方法为大多数应用领域的软件开发提供了一种实际的、有效的保证。
4.  UML(unified modeling language)语言
UML是面向对象技术领域内占主导地位的标准建模语言。它不仅统一了Booch方法、OMT方法和OOSE方法的表达系统结构的方式,而且对它们有了更进一步的发展,最终统一为大众接受的标准建模语言。UML是一种定义良好、易于表达、功能强大且普遍适用的建模语言。更多地,它以图形的方式来描述整个系统以及系统中各个组成部分动态或者静态的关系。它的作用域不限于支持面向对象的分析与设计,还支持从需求分析开始的软件开发全过程。
本章中使用的各种描述工资管理系统的图,就是UML系列图形中的一部分。

论坛徽章:
0
954 [报告]
发表于 2012-04-23 14:14 |只看该作者
额~~。。。火了。。

论坛徽章:
0
955 [报告]
发表于 2012-04-23 14:16 |只看该作者
6.4.1 需求分析:老板要的是这样一个工资程序
需求分析,是我们开发软件的第一步,无论这个软件是用于飞天登月的大型系统,还是仅供孩子们玩的游戏程序。所以,当小陈接到老板下达的指令后,他做的第一件事不是立即修改程序,而是先进行需求的分析,搞清楚老板到底要的是怎样一个工资程序。
根据老板的抱怨(在实际的开发中,这往往来自前期的用户调查),这个工资程序必须能够输入员工的工资数据,而输入数据又包括直接从数据文件读取和手工输入;完成数据输入以后,这个程序还要对工资数据进行处理,而这一部分也同样包括了计算最大的工资,以及根据员工的姓名对工资进行查询;最后,就是将所有的工资数据输出到文件,以便于下次直接读取。
经过这样的简单需求分析,小陈对老板要的工资程序就比较清楚了。为了让这些需求更加清晰而直观,小陈将其绘制成了UML用例图,老板要的工资程序,不过就是实现了这些用例的工资程序。

论坛徽章:
0
956 [报告]
发表于 2012-04-23 14:17 |只看该作者
这一部分太长了
没法一下发完

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
957 [报告]
发表于 2012-04-23 15:16 |只看该作者
无风之谷 发表于 2012-04-23 14:14
额~~。。。火了。。


是火了,很多人火气也大了。
你们也乐见其成,本来4.11该结束的也不结束了。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
958 [报告]
发表于 2012-04-23 15:49 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
959 [报告]
发表于 2012-04-23 16:07 |只看该作者
6.4.43  实现类的属性和行为
完成上面的分析与设计之后,小陈深深地伸了个懒腰。他知道,只要完成了程序中类的属性和行为的分析和设计,整个程序就相当于完成了一大半。接下来的工作,不过就是依葫芦画瓢,用C++这种开发语言将之前的设计表达出来,形成具体的程序而已。
按照之前的设计与分析,小陈决定首先实现最基础的Employee类:
// SalarySys.cpp
#include <ctime>          // 使用其中的时间函数
#include <string>         // 使用字符串对象

using namespace std;

// 枚举员工的级别
enum EmpLevel
{
                enumOfficer = 1,  // 高级员工
                enumStaff = 2                // 一般员工
};

// 员工类
class Employee
{
public:
                // 构造函数,根据员工的姓名和入职年份构造对象
                Employee(string strName, int nY)
                :m_strName(strName),m_nYear(nY) // 设定员工的姓名和入职年份
                {}
// Employee类的行为,这些行为都是供外界调用的,
// 所以将其访问级别设定为public
public:
                // 获得员工姓名
                string GetName()
                {
                        return m_strName;
                }
                // 获得员工入职年份
                int GetYear()
                {
                        return m_nYear;
                }
                // 获得员工级别
                EmpLevel GetLevel()
                {
                        return m_nLevel;
                }
                // 获得员工工资,因为这个行为同具体的员工类相关,
                // 不同的派生类有不同的行为(计算方法),所以在基类Employee中只是
                // 用纯虚函数表示接口,具体内容由其派生类实现
                virtual int GetSalary() = 0;

// GetWorkTime()只是供自身和自己的派生类似用,所以将其
// 访问级别设定为protected
protected:       
                // 获得在职时间,也就是现在年份减去入职年份
                // 因为这个行为只是供其派生类计算工资时使用,
                // 所以将其访问级别设定为protected
                int GetWorkTime()
                {
                        // 获得现在年份
                        time_t t = time(NULL);
                        struct tm* now = localtime(&t);
                        // time()函数获得的时间是以1900年为起点,所以这里需要
                        // 加上1900。同时,不满一年按照一年计算,所以最后要加1
                        return now->tm_year + 1900 - m_nYear + 1;
                 
                }
// Employee类的属性
// 因为这些属性也同样应当是其派生类具有的,需要由基类遗传给
// 它的派生类,所以这里使用protected访问控制,允许其派生类继承这些属性
protected:
                string m_strName;         // 姓名
                int m_nYear;                        // 入职年份
                EmpLevel m_nLevel;        // 级别
};
完成Employee类的实现后,就好像造房子打好了地基,小陈接着在其基础上,派生出具体的员工类Officer和Staff,分别完成具体的工资计算:
// 高级员工类
// 因为高级员工也是员工的一种,所以它可以从Employee员工类派生
class Officer : public Employee
{
public:
                // 构造函数
                // 调用基类Employee的构造函数,完成相同部分的构建
                Officer(string strName, int nY)
                :Employee(strName,nY)
                {
                        // 进行派生类独有的构建,设定员工的级别
                        m_nLevel = enumOfficer;
                }
        public:       
                // 对基类的纯虚函数进行定义,具体实现计算工资的行为
                virtual int GetSalary()
                {
                        return GetWorkTime()*5000;
                }
};
// 普通员工类
class Staff : public Employee
{
public:
                Staff(string strName, int nY)
                :Employee(strName,nY)
                {
                        m_nLevel = enumStaff;
                }
public:
                // 不同的派生类对相同的行为有不同的实现,
                // 这就是类的多态机制的体现
                virtual int GetSalary()
                {
                        return GetWorkTime()*1000;
                }
};
在员工类及其派生类的实现中,全面体现了面向对象的三大特征。首先,我们将所有员工,包括高级员工和普通员工的共有属性和行为封装成员工类Employee这个基类,这里体现的是类对属性和行为的封装;然后使用面向对象的继承机制从员工类Employee中派生出高级员工类Officer和普通员工类Staff,这样使得这两个派生类可以复用基类的代码,无须重复实现基类已有的属性和行为,例如员工的姓名和入职时间等共有属性,以及供外界访问的GetName()等接口函数。派生类所要做的,只是实现自己特有的属性和行为。例如,两个派生类各自对工资的计算方式不同,所以利用面向对象多态的机制,它们对基类提供的纯虚函数进行自定义,各自完成自己的GetSalary()这一函数的定义。
完成了具体的员工类的实现,接下来就是对这些员工对象进行管理的,最核心的SalarySys类。按照前面的设计,小陈用一个数组来保存这些员工对象的指针,同时又分别实现了SalarySys类的各个行为,对这些员工对象进行输入、查询和输出:
// 引入需要的头文件
#include <iostream>  // 屏幕输入输出
#include <fstream>        // 文件输入输出

// 定义SalarySys中数组的最大数据量,
// 也就是SalarySys最多能处理多少个数据
const int MAX = 100000;


// 工资管理类SalarySys
class SalarySys
{
public:
                // 构造函数,对属性进行初始化
                SalarySys()
                :m_nCount(0), // 设定当前数据量为0
                m_strFileName("SalaryData.txt") // 设定员工数据文件名
                {
                        // 对数组进行初始化
                        for(long i = 0; i<MAX; ++i)
                        {
                                m_arrEmp[i] = NULL;
                        }
               
                        // 读取员工数据文件
                        Read();
                }
               
                // 析构函数
                ~SalarySys()
                {
                        // 将员工数据写入文件
                        Write();
                        // 释放已经创建的员工对象
                        for(long i = 0; i<m_nCount; ++i)
                        {
                                delete m_arrEmp[i];  // 释放对象
                                m_arrEmp[i] = NULL;        // 将指针设置为NULL
                        }
                }
// SalarySys的公有行为
public:
                // 从员工数据文件读取已经输入的数据
                int Read()
                {
                        // 用于文件读取的中间变量
                        string strName = "";
                        int nLevel = 0;
                        int nYear = 0;

                        // 读取的数据个数
                        int i = 0;
                 
                        // 打开数据文件
                        ifstream in(m_strFileName);
                        if(in.is_open())
                        {
                                // 如果打开文件成功,构造无限循环进行读取
                                while(true)
                                {
                                        // 分别读取姓名、级别和入职年份
                                        in>>strName>>nLevel>>nYear;
                               
                                        // 判断是否读取正确,如果读取错误,
                                        // 例如读取到达文件末尾,则结束读取
                                        if(!in)
                                                break;
                                 
                                        // 根据读取的员工级别,分别创建不同的员工对象,
                                        // 并保存到m_arrEmp数组进行管理
                                        if( enumOfficer == nLevel)
                                        {
                                                // 根据员工姓名和入职年份,创建高级员工对象
                                                m_arrEmp[i] = new Officer(strName,nYear);
                                        }
                                        else if ( enumStaff == nLevel)
                                        {
                                                m_arrEmp[i] = new Staff(strName,nYear);
                                        }
                                        ++i; // 记录已经读取的数据数量
                                        // 如果读取的数量大于数组容量,则结束读取,否则开始下一次读取
                                        if(i>=MAX)                                               
                                                break;
                                }
                                // 输入完毕,关闭文件
                                in.close();
                        }
                        // 输出读取结果并返回读取的数据个数
                        cout<<"读取"<<i<<"个员工数据"<<endl;
                        m_nCount = i;
                       
                        return i;
                }
               
                // 将员工数据写入文件
                void Write()
                {
                        // 打开数据文件作为输出
                        ofstream o(m_strFileName);
                        if(o.is_open())
                        {
                                // 如果成功打开文件,则利用for循环逐个输出数组中保存的数据
                                for(int i = 0;i < m_nCount;++i)
                                {
                                        Employee* p = m_arrEmp[i];
                                        o<<p->GetName()<<"\t"         // 名字
                                        <<p->GetLevel()<<"\t"        // 级别
                                        <<p->GetYear()<<endl;        // 入职年份
                                }
                                // 输出完毕,关闭文件
                                o.close();
                        }
                }       
               
                // 手工输入员工数据
                int Input()
                {
                        // 新输入的数据保存在数组已有数据之后,
                        // 所以这里将已有数据个数m_nCount作为输入起点
                        int i = m_nCount;
                        // 提示输入
                        cout<<"请输入员工信息(名字 等级 入职年份),例如:Jiawei 1 1983"<<endl;
                        cout<<"-1表示输入结束"<<endl;
                        for(; i < MAX; ++i) // 初始化语句留空
                        {
                                // 利用for循环逐个输入
                                cout<<"请输入"<<i<<"号员工的信息:"<<endl;
                       
                                // 根据输入的数据创建具体的员工对象,并保存到数组
                                string strName = "";
                                int nL = 0;
                                int nY = 0;
                                // 获取用户输入
                                cin>>strName>>nL>>nY;
                         
                                // 对输入情况进行判断处理
                                if(!cin) // 如果输入错误,则重新输入
                                {
                                        cout<<"输入错误,请重新输入"<<endl;
                                        cin.clear(); // 清理输入标志位
                                        cin.sync();        // 清空键盘缓冲区
                                        --i; // 本次输入作废,不计算在内
                                        continue; // 开始下一次输入循环
                                }
                                else // 输入正确
                                {
                               
                                        // 检查是否输入结束
                                        if("-1" == strName)
                                        {
                                                break; // 结束输入循环
                                        }

                                        // 根据输入的数据,创建具体的员工对象并保存到数组
                                        if(enumOfficer == nL)
                                                m_arrEmp[i] = new Officer(strName,nY);
                                        else if(enumStaff == nL)
                                                m_arrEmp[i] = new Staff(strName,nY);
                                }
                        }
                        // 输入完毕,调整当前数组中的数据量
                        m_nCount = i;

                        // 返回本次输入的数据个数
                        return i;
                }

                // 获得最高工资的员工对象
                Employee* GetMax()
                {
                        // 表示结果的指针,初始值为NULL
                        Employee* pMax = NULL;
                        // 设定一个假想的当前最大值
                        int nMax = INT_MIN;
                        // 用for循环遍历数组中的每一个对象
                        for(int i = 0;i < m_nCount; ++i)
                        {
                                // 如果当前对象的工资高于当前最大值nMax,则将当前最大值
                                // 替换为当前对象的工资,并将当前对象的指针作为结果保存
                                // 这里使用的是基类Employeed 的指针,调用基类的公有接口函数                                                // GetSalry()。但是因为这个接口函数是虚函数,所以实际上,它们
                                // 将调用这个指针所指向的实际对象的相应函数。例如,这里通过指针
                                // pMax对GetSalary()        函数的调用,编译器将根据pMax这个基类
                                // 指针所指向的具体对象是Office还是Staff来决定到底是调用
                                // Officer类中的GetSalary()实现还是Staff类中的GetSalary()
                                // 实现。这就是面向对象中多态的体现——基类的指针,调用的却是
                                // 它所指向的具体派生类对象的函数。
                                if(m_arrEmp[i]->GetSalary()>nMax)
                                {
                                        // 则将当前对象记录为结果对象
                                        pMax = m_arrEmp[i];
                                        // 并将当前对象的工资记录为当前最大值
                                        nMax = pMax->GetSalary();
                                }
                        }
                        // 返回指向拥有最高工资的员工对象的指针
                        return pMax;
                }
       
                // 查询员工工资
                void Find()
                {
                        // 构造无限循环进行查询
                        while(true)
                        {
                                // 查询的姓名
                                string strName = "";
                                // 输入提示
                                cout<<"请输入要查询的员工名字(-1表示结束查询):"<<endl;
                                // 获取用户输入的员工序号并保存到n
                                cin>>strName;
                 
                                // 对用户输入进行检查
                                if(!cin) // 如果输入错误,提示重新输入
                                {
                                        cout<<"输入错误,请重新输入"<<endl;
                                        cin.clear();
                                        cin.sync();
                                        continue;
                                }
                                else if("-1" == strName) // 如果查询结束
                                {
                                        // 查询结束,用break结束循环
                                        cout<<"查询完毕,感谢使用!"<<endl;
                                        break;
                                }
                                // 记录是否找到查询的员工
                                bool bFind = false;
                                // 用for循环遍历所有员工对象,这个进行比对查找
                                for(int i = 0;i<m_nCount;++i)
                                {
                                        Employee* p = m_arrEmp[i];
                                        if(strName == p->GetName())
                                        {
                                                // 输出符合查询条件的员工信息
                                                cout<<"员工姓名:"<<p->GetName()<<endl;
                                                cout<<"员工工资:"<<p->GetSalary()<<endl;
                                                bFind = true; // 获得查询结果
                                                break;                        // 结束循环
                                        }
                                }

                                // 如果没有找到,则提示用户重新输入
                                if(!bFind)
                                {
                                        cout<<"无法找到名字为"<<strName<<"的员工。"<<endl;
        cout<<"请核对姓名,重新输入"<<endl;
                                }       
                        }
                }
// SlarySys类的属性
// 因为这个属性都只是供SalarySys类访问,
// 所以其访问级别设定为private
private:
                // 数据文件名,因为不可以修改,所以使用const关键字修饰
                const string m_strFileName;   
                Employee* m_arrEmp[MAX];  // 保存员工对象指针的数组
                int m_nCount; // 当前员工数
};
完成了工资系统类SalarySys之后,实际上就是万事俱备,只欠东风了。接下来就只需要在主函数中运用这些类来完成需求设计中的用例,那就是大功告成了:
int _tmain(int argc, TCHAR* argv[])
{
                // 创建一个SalarySys对象
                // 在构造函数中,它会首先去读取数据文件中的员工数据,
                // 完成““从文件读取”这一用例
                SalarySys sys;
       
                // 让用户输入数据,完成“手工输入”用例
                sys.Input();

                // 调用SalarySys的GetMax()函数,
                // 完成“计算最大值”用例
                Employee* pMax = sys.GetMax();
                if(NULL != pMax)
                {
                        cout<<"工资最高的员工是:"<<endl;
                        cout<<"名字:"<<pMax->GetName()<<endl;
                        cout<<"工资:"<<pMax->GetSalary()<<endl;
                }
               
                // 调用SalarySys类的Find()函数,完成“查询工资”用例
                sys.Find();
                
                // 最后,当sys对象析构的时候,会调用自己的Write()函数,
                // 完成“输出数据到文件”用例
                return 0;
}
有了面向对象思想和类的帮助,短短的几百行代码,小陈就完成了一个功能齐备的工资程序。从这里小陈也体会到,用面向对象思想进行分析与设计,更加接近我们思考问题、解决问题的思维模式,这使得工资程序的设计更加直观、更加自然、更加贴近现实的需求,其实现也更加思路清晰、更加容易。封装,可以让函数和她所操作的数据成为对象,可以起到很好的数据保护的作用;继承,可以复用共同的属性和行为,起到代码复用的作用。同时还可以很方便地对其进行扩展,从而支持更多更新的需求;多态,让我们可以以一致的调用方式,实现不同的操作行为。从而使得我们在设计中考虑得更多的是接口问题,而不用担心后面的实现问题。
当小陈将改写后的工资程序拿给老板使用以后,老板更是赞不绝口:
“不错不错,不仅能动态地计算各种员工的工资,并且时间变化以后,工资也会跟着变化。干得不错,啊哈哈……,下个月,涨工资。”
当再次听到老板的“涨工资”时,小陈已经没有先前那么激动了,他反问了一句:
“真的?”
“当然是真的,”老板立刻掩饰说,“我什么时候说话算数啊!”
听到这话,小陈也不去戳穿老板的伪装。现在在他看来,学好C++比涨工资更加重要,现在他已经越来越感受到C++的魅力,他已经开始爱上C++了。

论坛徽章:
0
960 [报告]
发表于 2012-04-23 16:09 |只看该作者
hellioncu 发表于 2012-04-23 15:16
是火了,很多人火气也大了。
你们也乐见其成,本来4.11该结束的也不结束了。


呵呵,
我们在这鹤蚌相争,他在这渔翁得利
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP