让我们戴上“面向对象”的有色眼镜来看这样一个熟悉的问题,要创建一个工资管理系统,该系统可以输入员工的姓名和入职时间。同时,员工分两个级别——普通员工和经理,两者的工资都根据入职时间计算,但是计算方式不同。其中,经理的工资等于工资10000元加上入职时间乘以5000元,也就是每年工资递增5000元,而普通员工的工资只是基本工资2000加上入职时间乘以200元。完成工资信息的录入后,系统就可以显示当前所有员工的信息并能够计算出所有员工的平均工资。
首先设计员工类和他派生出的经理类和普通员工类的设计。
新建头文件salary.h文件以存放类的申明。
1 #ifndef _SALARY_H_ 2 #define _SALARY_H_ 3 4 #include<string> 5 #include<iostream> 6 using namespace std; 7 8 //员工类 9 class Emplyee 10 { 11 public: 12 //构造函数 13 Emplyee(string strName, int nYears) 14 :m_strName(strName), 15 m_nYears(nYears) 16 // 利用构造函数参数对属性进行初始化 17 {}; 18 19 //员工类的行为 20 //提供一个纯虚函数作为公有接口,供外界获得员工工资 21 //经理和员工工资计算不同,需要纯虚函数供派生类自定义 22 virtual int GetSalary()=0; 23 //提供一个公有接口,供外界得到员工的名字 24 //内联函数 25 string GetName() 26 { 27 return m_strName; 28 }; 29 30 //员工类的属性 31 //需要遗传给它的派生类 32 //设置为protected 33 protected: 34 int m_nYears; 35 string m_strName; 36 }; 37 38 //经理类 39 //员工类中派生 40 class Manager : public Emplyee 41 { 42 public: 43 //使用基类的构造函数,完成初始化 44 Manager(string strName,int nYears) 45 :Emplyee(strName,nYears) 46 {}; 47 48 public: 49 //对基类提供的纯虚函数进行自定义 50 //同名函数在不同的派生类中可以有不同的实现 51 virtual int GetSalary() 52 { 53 return 5000 * m_nYears+10000; 54 } 55 }; 56 57 //普通员工类 58 //员工类中派生 59 class Worker : public Emplyee 60 { 61 public: 62 //使用基类的构造函数,完成初始化 63 Worker(string strName,int nYears) 64 :Emplyee(strName,nYears) 65 {}; 66 67 public: 68 //对基类提供的纯虚函数进行自定义 69 //同名函数在不同的派生类中可以有不同的实现 70 virtual int GetSalary() 71 { 72 return 200 * m_nYears+2000; 73 } 74 }; 75 76 #endif
上面这段代码有一组预编译命令#ifndef、#define、#endif,此为防止文件二次编译导致出现重定义错误,当然#pragma也有相同效果,具体区别请跳转至http://www.cnblogs.com/tenjl-exv/p/7469088.html
完成员工类及其派生类之后,就可以在工资管理系统类SalarySystem中创建对象并使用这些对象来代表员工,对工资进行管理。此段代码依旧放在salary.h文件后。SalarySystem实现如下:
1 //最大员工数 2 const int MAX_COUNT=100; 3 4 //工资管理系统 5 class SalarySystem 6 { 7 public: 8 //构造函数和析构函数 9 SalarySystem(void); 10 ~SalarySystem(void); 11 12 //工资管理系统的行为 13 public: 14 //输入员工信息 15 void InputEmplyee(void); 16 //显示员工信息 17 void DisplaySalary(void); 18 //计算平均工资 19 double GetAverSalary(void); 20 21 //工资管理系统的属性 22 private: 23 //当前员工总数 24 int m_nCount; 25 //创建指向员工对象的指针数组 26 Emplyee* m_arrEmplyee[MAX_COUNT]; 27 }; 28 29
这时SalarySystem类中的函数已经定义好了,但具体实现还没有完成,由于各个函数实现比较复杂,所以我们将实现放到跟.h头文件相对应的.cpp文件中:
1 //salary.cpp文件 2 #include"salary.h" 3 4 //构造函数 5 //内联 6 SalarySystem::SalarySystem(void) 7 { 8 m_nCount=0; 9 } 10 11 //析构函数 12 SalarySystem::~SalarySystem(void) 13 { 14 //清理资源 15 for(int i=0;i<m_nCount;++i) 16 { 17 Emplyee* pEmplyee = m_arrEmplyee[i]; 18 //销毁对象,释放内存 19 delete pEmplyee; 20 //将相应指针设为NULL,不可访问 21 m_arrEmplyee[i]=NULL; 22 } 23 } 24 25 //获取用户输入 26 void SalarySystem::InputEmplyee(void) 27 { 28 cout<<"请输入员工信息 " 29 <<"格式:员工姓名 入职时间 是否为经理级别 " 30 <<"例如: TenXiaocai 4 1 " 31 <<"输入end表示结束"<<endl; 32 string strName=" "; 33 int nYears=0; 34 bool bManager=false; 35 int nIndex=0; //员工个数 36 37 while(nIndex<MAX_COUNT) 38 { 39 //清空输入流 40 cin.clear(); 41 //获取用户数据 42 cin>>strName; 43 if("end"==strName) 44 break; 45 cin>>nYears>>bManager; 46 47 Emplyee* pEmplyee=NULL; 48 49 if(bManager) 50 { 51 pEmplyee=new Manager(strName,nYears); 52 //m_arrEmplyee[nIndex]=new Manager(strName,nYears); 53 } 54 else 55 { 56 pEmplyee=new Worker(strName,nYears); 57 //m_arrEmplyee[nIndex]=new Worker(strName,nYears); 58 } 59 60 //将创建的员工对象指针保存到数组中 61 m_arrEmplyee[nIndex]=pEmplyee; 62 ++nIndex; 63 } 64 m_nCount=nIndex; 65 } 66 67 //显示输出工资信息 68 void SalarySystem::DisplaySalary(void) 69 { 70 //显示工资信息 71 cout <<"工资管理系统"<<endl; 72 cout<<"当前员工总数:"<<m_nCount<< 73 " 平均工资是:"<<GetAverSalary()<<endl; 74 cout<<"员工具体工资信息如下:"<<endl; 75 76 //这里对GetSalary()函数的调用,编译器将 77 //根据pEmplyee这个基类指针所指向的具体对 78 //象是Manager还是Worker来决定到底是调用 79 //Manager类中的GetSalary()还是Worker类中 80 //这就是面向对象中 多态 的体现。 81 for(int i=0;i<m_nCount;++i) 82 { 83 Emplyee* pEmplyee = m_arrEmplyee[i]; 84 cout <<pEmplyee->GetName()<<" "<< 85 pEmplyee->GetSalary()<<endl; 86 //cout <<m_arrEmplyee[i]->GetName()<<" "<< 87 //m_arrEmplyee[i]->GetSalary()<<endl; 88 } 89 } 90 91 //计算平均工资 92 double SalarySystem::GetAverSalary() 93 { 94 int nTotal=0; 95 for(int i=0;i<m_nCount;++i) 96 { 97 Emplyee* pEmplyee = m_arrEmplyee[i]; 98 //nTotal+=m_arrEmplyee[i]->GetSalary(); 99 } 100 return (double)nTotal/m_nCount; 101 }
此段代码有几个点需要强调一下:
1.关于这段:
1 for(int i=0;i<m_nCount;++i) 2 { 3 Emplyee* pEmplyee = m_arrEmplyee[i]; 4 cout <<pEmplyee->GetName()<<" "<< 5 pEmplyee->GetSalary()<<endl; 6 //cout <<m_arrEmplyee[i]->GetName()<<" "<< 7 //m_arrEmplyee[i]->GetSalary()<<endl; 8 } 9 //此段代码中既然m_arrEmplyer已经是指向员工 10 //对象的指针数组,说明本身的数据类型就是员 11 //工指针,没必要再创建指针pEmplyee来进行操作 12 //后面也有两处是同样的情况, 13 //已经将可以替换的代码进行注释
2.有一个地方出现错误,现已纠正:
1 //计算平均工资 2 double SalarySystem::GetAverSalary() 3 { 4 int nTotal=0; 5 for(int i=0;i<m_nCount;++i) 6 { 7 //Emplyee* pEmplyee = m_arrEmplyee[i]; 8 //nTotal+=pEmplyee->GetSalary(); 9 nTotal+=m_arrEmplyee[i]->GetSalary(); 10 } 11 return (double)nTotal/m_nCount; 12 }
那么在完成工资系统类的创建之后,已是万事俱备,只欠东风了,我只需在主函数main里简单的使用这个类就完成了整个系统。
1 //main.cpp文件 2 #include "salary.h" 3 4 5 int main(int argc, char** argv) 6 { 7 //创建SalarySystem对象 8 SalarySystem nSalarySys; 9 //获取用户输入 10 nSalarySys.InputEmplyee(); 11 //显示工资信息 12 nSalarySys.DisplaySalary(); 13 14 return 0; 15 }
具体显示如下: