C++实验报告四(继承与派生实验)

C++实验报告四(继承与派生实验)

前些天做实验,题目是:编写一个程序实现某小型公司的人员信息管理系统。该公司雇员(Employee)包括经理(Manager),技术人员(Technician)、销售员(Salesman)和销售部经理(SalesManager)。要求存储这些人员的姓名、编号、级别、当月薪水,计算月薪并显示全部信息。程序要对所有人员有提升级别的功能。为简单起见,所有人员的初始级别均为1,然后进行升级,经理升为4级,技术人员和销售部经理升为3级,销售员仍为1级。月薪计算办法是 : 经理拿固定月薪8000元, 技术人员按每小时100元领取月薪,销售员按该当月销售额4% 提成,销售经理既拿固定月工资也领取销售提成,固定月工资为5000元, 销售提成为所管辖部门当月销售额的5% 。

以下是对象的继承和派生坑不得不跳啊!

代码如下,欢迎指正,写完那么多行,发现眼睛都花了!

#include<cstring>
#include <iostream>
using namespace std;

class Employee
{
public:
	Employee(string&);
	~Employee();
	string getname() {
		return name;
	}
	string getId() {
		return id;
	}
	int getlevel() {
		return level;
	}
	virtual double calculation_salary() { return 0; };
protected:
	char* name;					//姓名
	char* id;					//编号
	int level;					//级别
	double salary;				//薪水
	static int conut;			//员工人数
	static double Total_sales;	//部门销售总额
};

Employee::Employee(string& name){
	//cout << "员工构造成功:";
	id = new char[12];
	sprintf_s(id,12, "20201121%03d", conut);
	conut++;
	this->salary = 0;
	this->level = 1;
	this->name = new char[name.length() + 1];
	strcpy_s(this->name,name.length()+1,name.c_str());
};

Employee::~Employee()
{
	cout << "员工释放成功:";
	//使用了new动态申请空间的数据类型必须使用delete释放空间;使用malloc申请的需要使用free释放
	delete[] id;
	id = NULL;
	delete[] name;
	name = NULL;
};

class Manager : public Employee
{
public:
	Manager (string& );
	virtual double calculation_salary() {
		return salary;
	}
};

Manager::Manager(string& name) : Employee(name) {
	cout << "经理构造成功\n";
	salary = 8000;
	level += 3;
};

class Techician : public Employee
{
public:
	Techician(string&, float);
	virtual double calculation_salary() {
		salary = 100.0 * hours;
		return salary;
	}
protected:
	float hours;
};
Techician::Techician(string& name ,const float hours=0) : Employee(name) {
	cout << "技术人员构造成功\n";
	this->hours = hours;
	level += 2;
};

class Salesman :public Employee
{
public:
	Salesman(string &,double);
	virtual double calculation_salary() {
		salary = Monthly_sales * 0.04;
		return salary;
	}
private:
	double Monthly_sales;
};

Salesman::Salesman(string &name,double Monthly_sales = 0.0):Employee(name){
	cout << "销售员构造成功!\n";
	this->Monthly_sales = Monthly_sales;
	Total_sales += Monthly_sales;
}

class SalesManager :public Employee
{
public:
	SalesManager(string&);
	virtual double calculation_salary() {
		salary = 5000 + Total_sales * 0.05;
		return salary;
	}
};

SalesManager::SalesManager(string& name):Employee(name){
	level += 2;
	cout << "销售部经理构造成功!\n";
}

int Employee::conut = 1;
double Employee::Total_sales = 0.0;
void oputEmployee(Employee* Position, string& occupation) {
	cout << "姓名:" << Position->getname() << "\t编号:" << Position->getId() << "\t等级:" << Position->getlevel() << "\t月薪:" << Position->calculation_salary() << "\t岗位:" << occupation << endl;
}
int main()
{	
	cout << "——————请输入五个新员工的的姓名、工作岗位——————" << endl;
	cout << "—————岗位有经理、技术人员、销售员、销售部经理————" << endl;
	Employee* Emp[5] = { NULL };
	string name_Position[5][2];
	for (int i = 0; i < 5; i++)
	{
		double temp = 0.0;
		cout << "姓名:";
		cin >> name_Position[i][0];
		while (true)
		{
			cout << "岗位:";
			cin >> name_Position[i][1];
			if (name_Position[i][1] == "经理"|| name_Position[i][1] == "技术人员"||
				name_Position[i][1] == "销售员"|| name_Position[i][1] == "销售部经理") break;
			cout << "没有这个岗位!";
		}
		if (name_Position[i][1] == "经理") {
			Emp[i] = new Manager(name_Position[i][0]);
		}
		else if (name_Position[i][1] == "技术人员") {
			cout << "本月上班时长:";
			cin >> temp;
			Emp[i] = new Techician(name_Position[i][0], (float)temp);
		}
		else if (name_Position[i][1] == "销售员") {
			cout << "月销售额:";
			cin >> temp;
			Emp[i] = new Salesman(name_Position[i][0], temp);
		}
		else if (name_Position[i][1] == "销售部经理") {
			Emp[i] = new SalesManager(name_Position[i][0]);
		}
	}
	cout << "————————————————————————————" << endl;
	for (int i = 0; i < 5; i++) { oputEmployee(Emp[i],name_Position[i][1]); }
	cout << "辛苦了,已经完成管理!";
	for (int i = 0; i < 5; i++)
	{
		delete  Emp[i];
		Emp[i] = NULL;
	}
	return 0;
}

在这里写的代码很多感觉都是废代码,感觉代码十分笼统,教材书上的感觉比我少多了。

  • 定义数据成员类型
	char* name;					//姓名
	char* id;					//编号
	int level;					//级别
	double salary;				//薪水
	static int conut;			//员工人数
	static double Total_sales;	//部门销售总额

水平比较低,实在是折腾不来string类型是数据,开始也是使用string类型来定义name,id数据的,但是在构造函数对其赋初值时,各种报错(错误类型大概有指针悬空、内存溢出、还用“.c_str”安全模式等问题),人都会傻掉,所以改用char*类型数据,同时定义两个静态数据用于存储员工人数conut(产生员工ID)和存储销售部销售总额Total_sales(计算销售部经理的薪水),同时注意static数据的初始化,参考链接

  • 构造函数和构析函数
Employee::Employee(string& name){
	//cout << "员工构造成功:";
	id = new char[12];
	sprintf_s(id,12, "20201121%03d", conut);
	conut++;
	this->salary = 0;
	this->level = 1;
	this->name = new char[name.length() + 1];
	strcpy_s(this->name,name.length()+1,name.c_str());
};

Employee::~Employee()
{
	cout << "员工释放成功:";
	//使用了new动态申请空间的数据类型必须使用delete释放空间;使用malloc申请的需要使用free释放
	delete[] id;
	id = NULL;
	delete[] name;
	name = NULL;
};

每个人的想法不同,有些人觉得有这个构造函数就没有下面子类构造函数的事了,其实我也是有点这种感觉,但是,考虑到自己是初学者,为了避免错误的发生最好的办法就是把重点集中起来,同时可以把注意力集中到这段代码去,把重点分散开来,一旦出现错误,感觉满门忠烈,累死id就是自己了,这样的代价就是,感觉代码头重脚轻,不过后面自己去优化代码就变得有必要了,自己看得也舒服点,同时使用"string &"引用减少内存占用。构析函数中对使用了new分配空间的数据进行释放,使用delete[],注意的是将指针指向NULL,当然使用string类型的就省事了。

  • 使用sprintf_s()函数将数值转化为字符串产生员工ID,了解sprintf和sprintf_s的区别可以参考这个链接
sprintf_s(id,12, "20201121%03d", conut);

使用前需要将库函数包含进来,相比与其他的转化类型我更喜欢这种类型,因为输出的格式比较自由。

  • 虚函数和纯虚函数的选择
	virtual double calculation_salary() { return 0; };

其实对于这两个东西在本次实验中都是可以考虑的,首先我没有需要对基类(Employee)产生对象的需求,所以完全可以让他作接口,负责函数的统一,但是又考虑到基类还可以有大量的成员数据,对于这些成员数据总不能在建立一个基类用于继承吧,所以选择定义为虚基类,方便成员函数“calculation_salary()”进行重写。

  • 主函数
int main()
{	
	cout << "——————请输入五个新员工的的姓名、工作岗位——————" << endl;
	cout << "—————岗位有经理、技术人员、销售员、销售部经理————" << endl;
	Employee* Emp[5] = { NULL };
	string name_Position[5][2];
	for (int i = 0; i < 5; i++)
	{
		double temp = 0.0;
		cout << "姓名:";
		cin >> name_Position[i][0];
		while (true)
		{
			cout << "岗位:";
			cin >> name_Position[i][1];
			if (name_Position[i][1] == "经理"|| name_Position[i][1] == "技术人员"||
				name_Position[i][1] == "销售员"|| name_Position[i][1] == "销售部经理") break;
			cout << "没有这个岗位!";
		}
		if (name_Position[i][1] == "经理") {
			Emp[i] = new Manager(name_Position[i][0]);
		}
		else if (name_Position[i][1] == "技术人员") {
			cout << "本月上班时长:";
			cin >> temp;
			Emp[i] = new Techician(name_Position[i][0], (float)temp);
		}
		else if (name_Position[i][1] == "销售员") {
			cout << "月销售额:";
			cin >> temp;
			Emp[i] = new Salesman(name_Position[i][0], temp);
		}
		else if (name_Position[i][1] == "销售部经理") {
			Emp[i] = new SalesManager(name_Position[i][0]);
		}
	}
	cout << "————————————————————————————" << endl;
	for (int i = 0; i < 5; i++) { oputEmployee(Emp[i],name_Position[i][1]); }
	cout << "辛苦了,已经完成管理!";
	for (int i = 0; i < 5; i++)
	{
		delete  Emp[i];
		Emp[i] = NULL;
	}
	return 0;
}

本次实验就简单的实现五个员工的对象数组(一个经理,一个销售部经理,一个技术人员,两个销售员),通过创建基类对象指针Emp[5]—>向上转型(多态性)—>输出对象信息"oputEmployee(Employye *,Position)"—>释放空间。这里有个问题是因为使用向上转型,发现构析函数无法自动调用(自己不知道是啥原因,后面再搞),所以,需要手动调用基类的构析函数。

	for (int i = 0; i < 5; i++)
	{
		delete  Emp[i];
		Emp[i] = NULL;
	}
	return 0;
  • 实验结果

实验结果
突然感觉做销售好难呀!

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值