C++练习:人员信息管理程序计算不同职员的每月工资。

news2024/11/6 15:32:21

要求编写一个简单的人员信息管理程序,具体要求如下:

  1. 程序涉及到五个类,分别是employee,technician,salesman,manager,salsemanager。
    这五个类的关系为:employee是顶层父类;technician,salesman,manager是employee的子类;salesmanager是salesman,manager的子类。
  2. employee具有员工号,姓名,收入等属性,有设置姓名,获取姓名,获取员工号,获取收入等函数。
  3. technician的收入计算方法为工作小时数*时薪,另外具有设置工作小时数,时薪的函数,具有工作小时数和时薪的属性。
  4. salesman的收入计算方法为销售额*提成比例,另外具有设置销售额,提成比例的函数,具有销售额和提成比例的属性。
  5. manager的收入计算方法为固定月薪,另外具有设置固定月薪的函数,具有固定月薪的属性。
  6. salsemanager收入计算方法为销售额*提成比例+固定月薪。
  7. 要求利用employee类型的指针列表,包含8个子类对象(technician,salesman,manager,salsemanager每个类2个),通过相应方法输出这些对象的姓名(姓名的初始化通过键盘录入),员工号,收入。
employee.h
#pragma once
#include <iostream>
#include <string>
using namespace std;

class Employee
{
public:
	Employee();
	virtual ~Employee() { cout << "基类Employee" << endl; };	//观察析构函数调用顺序
	void SetName(string name = "");
	string GetName();

	void SetStaffID(string id = "");
	string GetStaffID();

	virtual void CalSalary() = 0;
	void SetSalary(float s);
	float GetSalary();

private:
	string m_sStaffID;
	string m_sName;
	float m_nSalary;
};
employee.cpp
#include "employee.h"
#include <iostream>
using namespace std;

Employee::Employee()
{
	m_nSalary = 0.0f;
}

void Employee::SetName(string name)
{
	if (name == "") {
		printf("请输入该员工的姓名:");
		cin >> name;
	}
	m_sName = name;
}

string Employee::GetName()
{
	return m_sName;
}

void Employee::SetStaffID(string id)
{
	if (id == "") {
		printf("请输入该员工的工号:");
		cin >> id;
	}
	m_sStaffID = id;
}

string Employee::GetStaffID()
{
	return m_sStaffID;
}

void Employee::SetSalary(float s)
{
	m_nSalary = s;
}

float Employee::GetSalary()
{
	return m_nSalary;
}
technician.h
#pragma once
#include "employee.h"
class Technician :
	public Employee
{
public:
	Technician();
	virtual ~Technician() { cout << "子类Technician"<<endl; };
	void Initialize();
	void SetWorkHour(float h) { m_nWorkHour = h; };
	float GetWorkHour() { return m_nWorkHour; };

	void SetHourFee(float fee) { m_nHourFee = fee; };
	float GetHourFee() { return m_nHourFee; }

	void CalSalary();
private:
	float m_nWorkHour;
	float m_nHourFee;
};
technician.cpp
#include <iostream>
#include "technician.h"
#include <string>
using namespace std;

Technician::Technician()
{
	m_nWorkHour = 0.0f;
	m_nHourFee = 0.0f;
}

void Technician::Initialize()
{
	SetName();
	SetStaffID();

	string name = GetName();
	string staffid;

	float workhour;
	printf("请输入%s的工作时长数:", name.c_str());
	cin >> workhour;
	SetWorkHour(workhour);

	float hourfee;
	printf("请输入%s的时薪:", name.c_str());
	cin >> hourfee;
	SetHourFee(hourfee);
}

void Technician::CalSalary()
{
	SetSalary(m_nWorkHour * m_nHourFee);
}
salesman.h
#pragma once
#include "employee.h"
class Salesman :
	virtual public Employee
{
public:
	Salesman();
	virtual ~Salesman() { cout << "子类Salesman"<<endl; };
	void Initialize();
	void SetSales(float sales) { m_nSales = sales; };
	float GetSales() { return m_nSales; };

	void SetPercent(float per) { m_nPercent = per; };
	float GetPercent() { return m_nPercent; };

	void CalSalary();
private:
	float m_nSales;
	float m_nPercent;
};
salesman.cpp
#include "salesman.h"
#include<iostream>
using namespace std;

Salesman::Salesman()
{
	m_nSales = 0.0f;
	m_nPercent = 0.0f;
}

void Salesman::Initialize()
{
	SetName();
	SetStaffID();

	string name = GetName();
	string staffid;

	float sales;
	printf("请输入%s的销售额:", name.c_str());
	cin >> sales;
	SetSales(sales);

	float percent;
	printf("请输入%s的提成比例:", name.c_str());
	cin >> percent;
	SetPercent(percent);
}

void Salesman::CalSalary()
{
	SetSalary(m_nSales*m_nPercent / 100);
}
manager.h
#pragma once
#include "employee.h"
class Manager :
	virtual public Employee
{
public:
	Manager();
	virtual ~Manager() { cout << "子类Manager"<<endl; };
	void Initialize();
	void SetFixedSalary(float salary) { m_nFixedSalary = salary; };
	float GetFixedSalary() { return m_nFixedSalary; };

	void CalSalary() { SetSalary(m_nFixedSalary); };
private:
	float m_nFixedSalary;
};
manager.cpp
#include "manager.h"
#include <iostream>
using namespace std;
Manager::Manager()
{
	m_nFixedSalary = 0.0f;
}

void Manager::Initialize()
{
	SetName();
	SetStaffID();

	string name = GetName();
	string staffid;

	float fixedsalary;
	printf("请输入%s的固定工资:", name.c_str());
	cin >> fixedsalary;
	SetFixedSalary(fixedsalary);
}
salesmanager.h
#pragma once
#include "salesman.h"
#include "manager.h"
class Salsemanager :
	public Salesman, public Manager
{
public:
	Salsemanager() {};
	virtual ~Salsemanager() { cout << "子类Salsemanager"<<endl; };
	void Initialize();
	void CalSalary();
};
salesmanager.cpp
#include "salsemanager.h"
#include<iostream>
using namespace std;

void Salsemanager::Initialize()
{

	SetName();
	SetStaffID();

	string name = GetName();
	string staffid;

	float sales;
	printf("请输入%s的销售额:", name.c_str());
	cin >> sales;
	SetSales(sales);

	float percent;
	printf("请输入%s的提成比例:", name.c_str());
	cin >> percent;
	SetPercent(percent);

	float fixedsalary;
	printf("请输入%s的固定工资:", name.c_str());
	cin >> fixedsalary;
	SetFixedSalary(fixedsalary);
}

void Salsemanager::CalSalary()
{
	float sales = GetSales();
	float percent = GetPercent();
	float fixedsalary = GetFixedSalary();
	Employee::SetSalary(sales * percent / 100 + fixedsalary);
}
main.cpp
#include "employee.h"
#include "manager.h"
#include "salesman.h"
#include "salsemanager.h"
#include "technician.h"
#include<iostream>
#include <string>
#include <list>
#include <Windows.h>
using namespace std;

int main()
{
	list<shared_ptr<Employee>> lEmployee;
	cout << "**************开始输入开发人员的相关信息***************" << endl;
	for (int i = 0; i < 2; ++i) {
		cout << "-------------------------------------------" << endl;
		shared_ptr<Technician> tec = make_shared<Technician>();
		tec->Initialize();
		tec->CalSalary();
		lEmployee.push_back(tec);
	}
	cout << "**************开始输入销售人员的相关信息***************" << endl;
	for (int i = 0; i < 2; ++i) {
		cout << "-------------------------------------------" << endl;
		shared_ptr<Salesman> sale = make_shared<Salesman>();
		sale->Initialize();
		sale->CalSalary();
		lEmployee.push_back(sale);
	}
	cout << "**************开始输入经理的相关信息***************" << endl;
	for (int i = 0; i < 2; ++i) {
		cout << "-------------------------------------------" << endl;
		shared_ptr<Manager> man = make_shared<Manager>();
		man->Initialize();
		man->CalSalary();
		lEmployee.push_back(man);
	}
	cout << "**************开始输入销售经理的相关信息***************" << endl;
	for (int i = 0; i < 2; ++i) {
		cout << "-------------------------------------------" << endl;
		shared_ptr<Salsemanager> saleman = make_shared<Salsemanager>();
		saleman->Initialize();
		saleman->CalSalary();
		lEmployee.push_back(saleman);
	}

	for (auto iter = lEmployee.begin(); iter != lEmployee.end(); ++iter) {
		printf("工号为 %s 的员工 %s 的本月薪资为:%f \n", (*iter)->GetStaffID().c_str(), (*iter)->GetName().c_str(), (*iter)->GetSalary());
	}
	return 0;
}

虚继承

本题在Employee、Salesman、Manager、Salesmanager类之间存在多重继承,使用一般的继承方式容易出现内存占用和二义性问题,需要采用 虚继承 的方式来解决这个问题。

继承有 普通继承虚继承 两种机制,默认继承方式是普通继承,如果要使用多重继承时,需要在继承方式里加上关键字virtual,即虚继承。

在C++中,多重继承可以让一个类同时继承于多个基类,从而实现更加灵活和复杂的面向对象编程。然而多重继承也会导致 同一个基类在派生类中出现多次,导致内存占用的增加以及代码调用二义性问题。

如下图所示,Salesmanager 类分别从 Sales 类和 Manager 类中继承了 Employee 类,这就会导致 Employee 类在 Salesmanager 类中出现两次。如果 Sales 类和 Manager 类中都有 Employee 类的成员变量或成员函数,那么在 Salesmanager 类中就会存在两份相同的 Employee 类成员,这就增加了内存占用,并且调用这些成员时,也会出现二义性问题。

多重继承

虚继承就是为了解决这个问题而出现的。虚继承允许一个类以虚继承方式继承一个基类,这样基类的成员变量和成员函数只在最终派生类中保留一份,而不是每个派生类都保留一份,这样就避免了菱形继承的问题,减少了内存占用和二义性问题。

虚继承会增加一些开销,它需要在派生类中维护虚基类的地址偏移量,以及查找基类成员的位置。

虚继承的用法
class Employee  {
public:
    int a;
};
 
class Sales  : virtual public Employee  {
public:
    int b;
};
 
class Manager  : virtual public Employee  {
public:
    int c;
};
 
class Salesmanager : public Manager , public Sales {
public:
    int d;
};

当采用虚继承后,类结构图如下所示,Salesmanager 中只有一份 Employee 类,当调用 Employee 类数据时,并不会发生冗余。

虚继承结构图

虚继承原理

在虚继承中,父类数据并不存放在虚继承的子类中,在虚继承的类中,会定义一个虚基表指针vbptr,指向虚基表。则虚基表中会存在偏移量,这个量就是表的地址到父类数据地址的距离

智能指针

本次练习题中采用shared_ptr智能指针,不用考虑指针的释放问题。

析构函数

本次练习题中析构函数声明为虚函数,也可以防止基类指针操作子类成员后出现内存泄漏的情况。在析构函数中输出相关信息方便观察指针释放时析构函数的调用次序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AUTOSAR AP 硬核知识点梳理(3)AUTOSAR AP 方法论和开发流程的最佳实践

一 Adaptive AUTOSAR 方法论 AUTOSAR AP开发方法论包括三个主要阶段,分别是: 1、架构和设计阶段: 在这个阶段,您需要确定系统的需求、功能和服务,并将它们分配到合适的Machine上。 根据个人习惯使用一些建模工具,例如[Simulink]、[ProVision]或[RTA-VRTE SDK]自带的DS…

我们不一样①

我们不一样① 从hello world开始 别人的hello world​​ 我们的hello world 代码展示 #include <stdio.h> int main(){printf("\033[31mhello world\033[0m"); getchar();return 0; } 此处用了 ANSI转义序列 ANSI转义序列是一种带内信号的转义序列标准&am…

代码随想录算法训练营第23期day27|93.复原IP地址、78.子集、90.子集II

目录 一、&#xff08;leetcode 93&#xff09;复原IP地址 二、&#xff08;leetcode 78&#xff09;子集 三、&#xff08;leetcode 90&#xff09;子集II 一、&#xff08;leetcode 93&#xff09;复原IP地址 力扣题目链接 状态&#xff1a;没有写出来&#xff0c;待回顾…

Python —— 验证码的处理执行JavaScript语句

1、验证码的处理 1、概述&绕过验证码的方案 很多的网站都在登录页面加入了识别文字&#xff0c;识别图片&#xff0c;拖动拼图的验证码方式来防止爬虫、恶意注册 等&#xff0c;如果是做自动化&#xff0c;需要绕过验证码才能进入下一步操作&#xff0c;那么有4种方案可以…

深入探讨 Golang 中的追加操作

通过实际示例探索 Golang 中的追加操作 简介 在 Golang 编程领域&#xff0c;append 操作是一种多才多艺的工具&#xff0c;使开发人员能够动态扩展切片、数组、文件和字符串。在这篇正式的博客文章中&#xff0c;我们将踏上一段旅程&#xff0c;深入探讨在 Golang 中进行追加…

基于跳蛛优化的BP神经网络(分类应用) - 附代码

基于跳蛛优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于跳蛛优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.跳蛛优化BP神经网络3.1 BP神经网络参数设置3.2 跳蛛算法应用 4.测试结果&#xff1a;5.M…

eltable el-tooltip__popper 换行、字体、颜色等调整

show-overflow-tooltip属性 element-ui表格 默认情况下若内容过多会折行显示&#xff0c;若需要单行显示可以使用show-overflow-tooltip属性&#xff0c;它接受一个Boolean&#xff0c;为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。 默认情况 element-ui表格 sh…

【练习题】二.栈和队列

1.蒋编号为0和[的两个栈存放于一个数组空间 V[m]中,栈底分别处于数组的两端。当第0号栈的栈顶播针 top[0]等F-1 时该戍为空:当第1号栈的栈顶指针 top[I]等于 m 时,该栈为空两个栈均从两端向中间增长 (见图 3.2)。试编写双栈初始化,判渐栈空、栈满、进栈和出栈等算法的两数。…

5年经验之谈 —— 总结自动化测试与性能测试的区别!

很多刚刚接触自动化测试和性能测试的同学感觉性能测试和自动化测试是没什么区别的&#xff0c;就像小编刚刚接触自动化测试和性能测试的时候一样&#xff0c;区别就是&#xff1a;自动化测试是一个用户在测试&#xff0c;而性能测试需要并发&#xff0c;需要设计各种场景。测试…

论文辅助笔记:t2vec 数据预处理

1 波尔图数据 curl http://archive.ics.uci.edu/ml/machine-learning-databases/00339/train.csv.zip -o data/porto.csv.zip 这条命令使用 curl 从给定的URL下载一个名为 train.csv.zip 的压缩文件&#xff0c;并将其保存为 data/porto.csv.zip。 unzip data/porto.csv.zip 使…

python实现矩阵转置

使用列表推导式实现矩阵转置 matrix [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] print([[row[i] for row in matrix]for i in range(4)])使用内置函数来实现矩阵转置 matrix [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] print(list(map(list, zip(*matrix))))使用…

softplc windows 安装测试

下载 .NET 6.0 (Linux、macOS 和 Windows) 安装后 在这里 The command could not be loaded, possibly because: * You intended to execute a .NET application: The application restore does not exist. * You intended to execute a .NET SDK command: No…

如何利用IP定位技术进行反欺诈?

网络欺诈风险是指在互联网和数字领域中&#xff0c;存在各种类型的欺诈活动&#xff0c;旨在欺骗个人、组织或系统以获得非法获益。以下是一些常见的网络欺诈风险类型&#xff1a; 身份盗用&#xff1a;这是一种欺诈行为&#xff0c;涉及盗取他人的个人身份信息&#xff0c;如姓…

基于Java的汽车维修预约管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

电度表和电能表是一样的吗?

电度表和电能表都是用于测量电能的仪表&#xff0c;但它们之间存在一些区别。接下来&#xff0c;小编来为大家介绍下电度表和电能表的区别有哪些吧&#xff0c;一起来看下&#xff01; 电度表是传统的机械式电能表&#xff0c;它通过测量电流和电压的乘积来计算电能&#xff0c…

数字化营销系统的重点功能?利用数字化营销系统为企业降本增效?

如今&#xff0c;越来越多的企业开始关注数字化营销&#xff0c;并利用数字化手段推动新的营销方式、模式和策划。数字化营销的重要性不言而喻&#xff0c;下面我们来了解一下数字化营销的优势有哪些&#xff1f; 1. 数字化营销可以更大程度地为用户提供足够的信息。 通过商品…

【数据结构初阶】九、排序的讲解和实现(直接插入 \ 希尔 \ 直接选择 \ 堆 \ 冒泡 -- C语言)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【数据结构初阶】八、非线性表里的二叉树&#xff08;二叉树的实现 -- C语言链式结构&#xff09;-CSDN博客 排序 排序的概念 所谓排序&#xff0c;就是使一串记录&#xff0c;按照…

[人工智能-综述-12]:第九届全球软件大会(南京)有感 -1-程序员通过大模型增强自身软件研发效率的同时,也在砸自己的饭碗

目录 前言&#xff1a; 一、什么是软件工程 1.1 什么软件工程 1.2 影响软件开发效能的三大因素 1.3 AI大模型是如何提升软件工程全过程效率的 二、AI大模型如何提升软件项目管理效率 2.1 概述 2.2 案例或工具 三、AI大模型如何提升软件开发工具的效率 3.1 概述 3.2 …

python使用grpc

proto 首先编写proto&#xff0c;也可以根据对象生成proto syntax "proto3";package text;service TextSender{rpc Send(Text) returns (SendResponse);rpc Resend(Text) returns (SendResponse); }message Text{string text 1; }message SendResponse{bool suce…