《编码规范和测试方法——C/C++版》作业 ·005——设计一组员工类

问题描述

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,采用
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

God-Excious

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值