问题描述
Cola公司的雇员分为以下若干类:
ColaEmployee :所有员工总的父类
属性:员工的姓名,员工的生日月份
方法:getSalary(int month) 根据参数月份来确定工资,如果该月员工过生日,则公司会额外奖励100 元
SalariedEmployee :ColaEmployee 的子类,拿固定工资的员工
属性:月薪
HourlyEmployee :ColaEmployee 的子类,按小时拿工资的员工,每月工作超出160小时的部分按照1.5 倍工资发放
属性:每小时的工资、每月工作的小时数
SalesEmployee :ColaEmployee 的子类,销售人员,工资由月销售额和提成率决定
属性:月销售额、提成率
定义一个类Company,在该类中写一个方法,调用该方法可以打印出某月某个员工的工资数额。
写一个测试类TestCompany,在main方法,把若干各种类型的员工放在一个ColaEmployee 数组里,并单元测试输出数组中每个员工当月的工资。
参考解答
项目结构
详细代码
ColaEmployee.h文件
#ifndef COLAEMPLOYEE_H
#define COLAEMPLOYEE_H
#include <string> // 为了正常引入string,不得已
using namespace std; // 为了正常引入string,不得已
class ColaEmployee
{
public:
ColaEmployee();
ColaEmployee(string n, int bm);
virtual ~ColaEmployee();
string getName()const;
int getBirthmonth()const;
virtual double getSalary(int m)const=0;
private:
string name;
int birthmonth;
};
#endif // !COLAEMPLOYEE_H
ColaEmployee.cpp文件
#include "pch.h"
#include "ColaEmployee.h"
/*
* 功能:
* ColaEmployee的缺省构造函数
* 参数:
* void
* 返回值:
* 无
* 说明:
* 默认员工姓名为空串""
* 默认员工生日月份为1月
* 创建时间:
* 2020-03-18 10:26:05
* 作者:
* Excious
**/
ColaEmployee::ColaEmployee()
:name(""), birthmonth(1)
{
}
/*
* 功能:
* ColaEmployee的构造函数
* 参数:
* n in 员工的姓名
* bm in 员工的生日月份
* 返回值:
* 无
* 说明:
* 如果 bm 不在1-12中,则将其设置为1
* 创建时间:
* 2020-03-18 10:32:27
* 作者:
* Excious
**/
ColaEmployee::ColaEmployee(string n, int bm)
:name(n), birthmonth((bm > 0 && bm < 13) ? bm : 1)
{
}
/*
* 功能:
* ColaEmployee的析构函数
* 参数:
* void
* 返回值:
* 无
* 创建时间:
* 2020-03-18 10:34:07
* 作者:
* Excious
**/
ColaEmployee::~ColaEmployee()
{
}
/*
* 功能:
* 返回员工姓名
* 参数:
* void
* 返回值:
* 员工姓名
* 创建时间:
* 2020-03-18 13:12:30
* 作者:
* Excious
**/
string ColaEmployee::getName() const
{
return this->name;
}
/*
* 功能:
* 返回员工生日月份
* 参数:
* void
* 返回值:
* 员工生日月份
* 创建时间:
* 2020-03-18 13:12:54
* 作者:
* Excious
**/
int ColaEmployee::getBirthmonth() const
{
return this->birthmonth;
}
SalariedEmployee.h文件
#ifndef SALARIEDEMPLOYEE_H
#define SALARIEDEMPLOYEE_H
#include "ColaEmployee.h"
class SalariedEmployee :
public ColaEmployee
{
public:
SalariedEmployee();
SalariedEmployee(string n, int bm, double sal_m);
virtual ~SalariedEmployee();
virtual double getSalary(int m)const;
private:
double salary_month;
};
#endif // !SALARIEDEMPLOYEE_H
SalariedEmployee.cpp文件
#include "pch.h"
#include "SalariedEmployee.h"
/*
* 功能:
* SalariedEmployee类的缺省构造函数
* 参数:
* void
* 返回值:
* 无
* 说明:
* 默认月薪工姓名为空串""
* 默认月薪工生日月份为1月
* 默认月薪工的月薪为0.00
* 创建时间:
* 2020-03-18 10:45:40
* 作者:
* Excious
**/
SalariedEmployee::SalariedEmployee()
:salary_month(0.00)
{
}
/*
* 功能:
* SalariedEmployee类的构造函数
* 参数:
* n in 月薪工的姓名
* bm in 月薪工的生日月份
* sal_m in 月薪工的月薪
* 返回值:
* 无
* 说明:
* 如果 bm 不在1-12中,则将其设置为1
* 如果 sal_m < 0,则将其设置为0.00
* 创建时间:
* 2020-03-18 10:48:57
* 作者:
* Excious
**/
SalariedEmployee::SalariedEmployee(string n, int bm, double sal_m)
:ColaEmployee(n, bm), salary_month(sal_m < 0 ? 0.00 : sal_m)
{
}
/*
* 功能:
* SalariedEmployee类的析构函数
* 参数:
* void
* 返回值:
* 无
* 创建时间:
* 2020-03-18 10:56:45
* 作者:
* Excious
**/
SalariedEmployee::~SalariedEmployee()
{
}
/*
* 功能:
* 返回当前月薪工月份为 m 时的工资
* 参数:
* m in 月份
* 返回值:
* 月薪工的第 m 月的工资
* 说明:
* 如果 m 不在1~12以内,则将其设置为1
* 如果 m 为生日的月份,则额外奖励100.00元
* 创建时间:
* 2020-03-18 11:01:07
* 作者:
* Excious
**/
double SalariedEmployee::getSalary(int m)const
{
m = (m > 0 && m < 13) ? m : 1; // 调整错误月份
return this->salary_month + (m == this->getBirthmonth() ? 100.00 : 0.00);
}
HourlyEmployee.h文件
#ifndef HOURLYEMPLOYEE_H
#define HOURLYEMPLOYEE_H
#include "ColaEmployee.h"
class HourlyEmployee :
public ColaEmployee
{
public:
HourlyEmployee();
HourlyEmployee(string n, int bm, double sal_h, int h);
virtual ~HourlyEmployee();
virtual double getSalary(int m)const;
private:
double salary_hour;
int hours;
};
#endif // !HOURLYEMPLOYEE_H
HourlyEmployee.cpp文件
#include "pch.h"
#include "HourlyEmployee.h"
/*
* 功能:
* HourlyEmployee类的缺省构造函数
* 参数:
* void
* 返回值:
* 无
* 说明:
* 默认小时工姓名为空串""
* 默认小时工生日月份为1月
* 默认小时工时薪为0.00
* 默认小时工每月工作小时数为0
* 创建时间:
* 2020-03-18 11:33:59
* 作者:
* Excious
**/
HourlyEmployee::HourlyEmployee()
:salary_hour(0.00), hours(0)
{
}
/*
* 功能:
* HourlyEmployee类的构造函数
* 参数:
* n in 小时工的姓名
* bm in 小时工的生日月份
* sal_h in 小时工的时薪
* h in 小时工的每月工作小时数
* 返回值:
* 无
* 说明:
* 如果 bm 不在1-12中,则将其设置为1
* 如果 sal_h < 0,则将其设置为0.00
* 如果 h < 0,则将其设置为0
* 创建时间:
* 2020-03-18 12:04:21
* 作者:
* Excious
**/
HourlyEmployee::HourlyEmployee(string n, int bm, double sal_h, int h)
:ColaEmployee(n, bm), salary_hour(sal_h < 0.00 ? 0.00 : sal_h), hours(h < 0 ? 0 : h)
{
}
/*
* 功能:
* HourlyEmployee类的析构函数
* 参数:
* void
* 返回值:
* 无
* 创建时间:
* 2020-03-18 12:09:53
* 作者:
* Excious
**/
HourlyEmployee::~HourlyEmployee()
{
}
/*
* 功能:
* 返回当前时薪工月份为 m 时的工资
* 参数:
* m in 月份
* 返回值:
* 时薪工的第 m 月的工资
* 说明:
* 如果 m 不在1~12以内,则将其设置为1
* 如果 m 为生日的月份,则额外奖励100.00元
* 如果工作超出160小时,超过部分按照1.5倍工资发放
* 由于一行的表达式比较长,未给成员(salary_howr、hours、getBirthmonth)加上【this->】
* 创建时间:
* 2020-03-18 12:13:08
* 作者:
* Excious
**/
double HourlyEmployee::getSalary(int m) const
{
m = (m > 0 && m < 13) ? m : 1; // 调整错误月份
return salary_hour * (hours <= 160 ? hours : 160) + 1.5 * salary_hour * (hours > 160 ? hours - 160 : 0) + (m == getBirthmonth() ? 100.00 : 0);
}
SalesEmployee.h文件
#ifndef SALESEMPLOYEE_H
#define SALESEMPLOYEE_H
#include "ColaEmployee.h"
class SalesEmployee :
public ColaEmployee
{
public:
SalesEmployee();
SalesEmployee(string n, int bm, double s, double r);
virtual ~SalesEmployee();
virtual double getSalary(int m)const;
private:
double sales;
double rate;
};
#endif // !SALESEMPLOYEE_H
SalesEmployee.cpp文件
#include "pch.h"
#include "SalesEmployee.h"
/*
* 功能:
* SalesEmployee类的缺省构造函数
* 参数:
* void
* 返回值:
* 无
* 说明:
* 默认销售工姓名为空串""
* 默认销售工生日月份为1月
* 默认销售工销售额为0.00
* 默认销售工提成率为0.00
* 创建时间:
* 2020-03-18 12:49:05
* 作者:
* Excious
**/
SalesEmployee::SalesEmployee()
:sales(0.00), rate(0.00)
{
}
/*
* 功能:
* SalesEmployee类的构造函数
* 参数:
* n in 销售工的姓名
* bm in 销售工的生日月份
* s in 销售工的销售额
* r in 销售工的提成率
* 返回值:
* 无
* 说明:
* 如果 bm 不在1-12中,则将其设置为1
* 如果 s < 0,则将其设置为0.00
* 如果 r < 0,则将其设置为0.00
* 如果 r > 1,则将其设置为1.00
* 创建时间:
* 2020-03-18 12:41:07
* 作者:
* Excious
**/
SalesEmployee::SalesEmployee(string n, int bm, double s, double r)
:ColaEmployee(n, bm), sales(s < 0.00 ? 0.00 : s), rate(r < 0.00 ? 0.00 : (r > 1.00 ? 1.00 : r))
{
}
/*
* 功能:
* SalesEmployee类的析构函数
* 参数:
* void
* 返回值:
* 无
* 创建时间:
* 2020-03-18 12:53:50
* 作者:
* Excious
**/
SalesEmployee::~SalesEmployee()
{
}
/*
* 功能:
* 返回当前销售工月份为 m 时的工资
* 参数:
* m in 月份
* 返回值:
* 销售工的第 m 月的工资
* 说明:
* 如果 m 不在1~12以内,则将其设置为1
* 如果 m 为生日的月份,则额外奖励100.00元
* 创建时间:
* 2020-03-18 12:13:08
* 作者:
* Excious
**/
double SalesEmployee::getSalary(int m) const
{
return this->sales * this->rate + (m == this->getBirthmonth() ? 100.00 : 0);
}
Company.h文件
#ifndef COMPANY_H
#define COMPANY_H
#include "ColaEmployee.h"
class Company
{
public:
void showSalary_emp_mon(ColaEmployee* ce, int m)const;
};
#endif // !COMPANY_H
Company.cpp文件
#include "pch.h"
#include "Company.h"
#include <iostream>
using namespace std;
/*
* 功能:
* 打印一个员工在月份 m 时的工资
* 参数:
* ce in 指向员工的指针
* m in 月份
* 返回值:
* void
* 创建时间:
* 2020-03-18 18:22:10
* 作者:
* Excious
**/
void Company::showSalary_emp_mon(ColaEmployee* ce, int m) const
{
cout << "员工信息如下:" << endl;
cout << " 【 姓 名 】:" << ce->getName() << endl;
cout << " 【" << m << "月份工资】:" << ce->getSalary(m) << endl;
}
TestCompany.cpp文件
#include "pch.h"
#include "SalariedEmployee.h"
#include "HourlyEmployee.h"
#include "SalesEmployee.h"
#include "Company.h"
#include <iostream>
#define N 19
using namespace std;
class TestCompany
{
public:
static void test(ColaEmployee* ce[], int m);
};
int main()
{
ColaEmployee* ce[N]
{
// 异常输入数据——12组
// 月薪工【姓名:""】 【生月:1】【月薪:0.00】 { 基础应得:0.00 }
new SalariedEmployee(),
// 月薪工【姓名:"异常月薪工1号"】【生月:1】【月薪:0.00】 { 基础应得:0.00 }
new SalariedEmployee("异常月薪工1号", -1, -1500.00),
// 月薪工【姓名:"异常月薪工2号"】【生月:1】【月薪:0.00】 { 基础应得:0.00 }
new SalariedEmployee("异常月薪工2号", 13, 0.00),
// 时薪工【姓名:""】 【生月:1】【时薪:0.00】 【小时:0】 { 基础应得:0.00 }
new HourlyEmployee(),
// 时薪工【姓名:"异常时薪工1号"】【生月:1】【时薪:0.00】 【小时:0】 { 基础应得:0.00 }
new HourlyEmployee("异常时薪工1号", -2, -100.00, 150),
// 时薪工【姓名:"异常时薪工2号"】【生月:1】【时薪:100.00】【小时:0】 { 基础应得:0.00 }
new HourlyEmployee("异常时薪工2号", 14, 100.00, -2),
// 时薪工【姓名:"异常时薪工3号"】【生月:7】【时薪:0.00】 【小时:170】 { 基础应得:0.00 }
new HourlyEmployee("异常时薪工3号", 7, -100.00, 170),
// 销售工【姓名:""】 【生月:1】【销售额:0.00】 【提成率:0.00】 { 基础应得:0.00 }
new SalesEmployee(),
// 销售工【姓名:"异常销售工1号"】【生月:1】【销售额:0.00】 【提成率:0.50】 { 基础应得:0.00 }
new SalesEmployee("异常销售工1号", 3, -200.00, 0.50),
// 销售工【姓名:"异常销售工2号"】【生月:1】【销售额:100.00】【提成率:0.00】 { 基础应得:0.00 }
new SalesEmployee("异常销售工2号", 7, 100.00, -0.25),
// 销售工【姓名:"异常销售工3号"】【生月:1】【销售额:0.00】 【提成率:0.00】 { 基础应得:0.00 }
new SalesEmployee("异常销售工3号", -1, -100.00, -0.25),
// 销售工【姓名:"异常销售工4号"】【生月:1】【销售额:100.00】【提成率:1.00】 { 基础应得:100.00 }
new SalesEmployee("异常销售工4号", 13, 100.00, 1.38),
// 月薪工数据——2组
// 月薪工【姓名:"月薪工1号"】【生月:1】【月薪:1500.00】 { 基础应得:1500.00 }
new SalariedEmployee("月薪工1号", 1, 1500.00),
// 月薪工【姓名:"月薪工2号"】【生月:3】【月薪:2500.10】 { 基础应得:2500.10 }
new SalariedEmployee("月薪工2号", 3, 2500.10),
// 时薪工数据——3组
// 时薪工【姓名:"时薪工1号"】【生月:1】【时薪:15.50】 【小时:2】 { 基础应得:31.00 }
new HourlyEmployee("时薪工1号", 1, 15.50, 2),
// 时薪工【姓名:"时薪工2号"】【生月:3】【时薪:1.60】 【小时:160】 { 基础应得:256.00 }
new HourlyEmployee("时薪工2号", 3, 1.60, 160),
// 时薪工【姓名:"时薪工3号"】【生月:3】【时薪:2.00】 【小时:170】 { 基础应得:350.00 }
new HourlyEmployee("时薪工3号", 3, 2.00, 170),
// 销售工数据——2组
// 销售工【姓名:"销售工1号"】【生月:1】【销售额:100.00】【提成率:0.50】 { 基础应得:50.00 }
new SalesEmployee("销售工1号", 1, 100.00, 0.50),
// 销售工【姓名:"销售工2号"】【生月:3】【销售额:100.00】【提成率:0.50】 { 基础应得:22.00 }
new SalesEmployee("销售工2号", 3, 100.00, 0.22)
};
// 参考1月实际薪资值:100 | 100 | 100 | 100 | 100 | 100 | 0 | 100 | 0 | 0 | 100 | 200 | 1600 | 2500.1 | 131 | 256 | 350 | 150 | 22
// 测试结果:全部正确
TestCompany::test(ce, 1);
cout << "------------------------------------" << endl;
// 参考3月实际薪资值:0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 100 | 0 | 0 | 100 | 1500 | 2600.1 | 31 | 356 | 450 | 50 | 122
// 测试结果:全部正确
TestCompany::test(ce, 3);
cout << "------------------------------------" << endl;
for (int i = 0; i < N; ++i)
delete ce[i];
return 0;
}
/*
* 功能:
* 打印出所有员工案例的工资
* 参数:
* ce in 父类指针的数组
* m in 月份
* 返回值:
* void
* 说明:
* 函数使用宏变量 N 作为父类指针数组的元素个数
* 创建时间:
* 2020-03-18 21:15:21
* 作者:
* Excious
**/
void TestCompany::test(ColaEmployee * ce[], int m)
{
Company c;
for (int i = 0; i < N; ++i)
{
c.showSalary_emp_mon(ce[i], m);
}
}
运行结果
运行文本如下:
员工信息如下:
【 姓 名 】:
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常月薪工1号
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常月薪工2号
【1月份工资】:100
员工信息如下:
【 姓 名 】:
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常时薪工1号
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常时薪工2号
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常时薪工3号
【1月份工资】:0
员工信息如下:
【 姓 名 】:
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常销售工1号
【1月份工资】:0
员工信息如下:
【 姓 名 】:异常销售工2号
【1月份工资】:0
员工信息如下:
【 姓 名 】:异常销售工3号
【1月份工资】:100
员工信息如下:
【 姓 名 】:异常销售工4号
【1月份工资】:200
员工信息如下:
【 姓 名 】:月薪工1号
【1月份工资】:1600
员工信息如下:
【 姓 名 】:月薪工2号
【1月份工资】:2500.1
员工信息如下:
【 姓 名 】:时薪工1号
【1月份工资】:131
员工信息如下:
【 姓 名 】:时薪工2号
【1月份工资】:256
员工信息如下:
【 姓 名 】:时薪工3号
【1月份工资】:350
员工信息如下:
【 姓 名 】:销售工1号
【1月份工资】:150
员工信息如下:
【 姓 名 】:销售工2号
【1月份工资】:22
------------------------------------
员工信息如下:
【 姓 名 】:
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常月薪工1号
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常月薪工2号
【3月份工资】:0
员工信息如下:
【 姓 名 】:
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常时薪工1号
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常时薪工2号
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常时薪工3号
【3月份工资】:0
员工信息如下:
【 姓 名 】:
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常销售工1号
【3月份工资】:100
员工信息如下:
【 姓 名 】:异常销售工2号
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常销售工3号
【3月份工资】:0
员工信息如下:
【 姓 名 】:异常销售工4号
【3月份工资】:100
员工信息如下:
【 姓 名 】:月薪工1号
【3月份工资】:1500
员工信息如下:
【 姓 名 】:月薪工2号
【3月份工资】:2600.1
员工信息如下:
【 姓 名 】:时薪工1号
【3月份工资】:31
员工信息如下:
【 姓 名 】:时薪工2号
【3月份工资】:356
员工信息如下:
【 姓 名 】:时薪工3号
【3月份工资】:450
员工信息如下:
【 姓 名 】:销售工1号
【3月份工资】:50
员工信息如下:
【 姓 名 】:销售工2号
【3月份工资】:122
------------------------------------
顾虑与思考
1、可以考虑给小时工加上一个小时数超过一个月总的小时数的判别(这里就不做了)
2、参考了网上关于销售额的说法,有些说法指出,负数销售额一般是指销售退回大于销售收入
也就是说这种销售额的定义是【销售额 = 销售收入 - 销售退回】
而百度百科上给出的销售额定义是【销售额 = 销售量 × 平均价格】
既然题目也没有特别说明,那就按照销售额恒非负来算吧。
3、关于非法输入与缺省,如果有特殊要求,可以根据具体情况做变动
所有类中的缺省构造函数,我都将属性默认设置为最小,比如月份设置为1、工资设置为0……
大多数非法输入我都改为最小,比如将月份(-1、13)修正为1、将薪资(-500.00)修正为(0.00)
4、认为提成率应该不会超过1.00,如果可以,只要将超过1.00的修正去除
5、在最终的测试部分,遇到了很费解的bug,
调试的时候发现临时构造出来的对象会在构造完后瞬间被析构掉,导致最后父类指针调用异常。
最后有三种方法可以解决
(1).将所有析构函数去掉——可能会导致内存泄漏,不采用
(2).将所有子类对象用变量存储——代码量惊人,不采用
(3).用new来创建对象——可以用父类指针集中delete,采用