C++多态
哔哩哔哩:https://www.bilibili.com/video/BV1et411b73Z?p=138&spm_id_from=pageDriver
主函数
#include<iostream>
#include <csignal>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include "wokerSMS.h"
using namespace std;
extern void clear()//清屏函数
{
#if defined(_WIN32)
system("pause");
system("cls");
#else
// char buf[1024]={0};
std::cout << "请输入回车键继续……" << std::endl;
// fgets(buf,1024,stdin);
char c;
std::cin.get();
while ((c = getchar()) != '\n' && c != EOF);
system("clear");
#endif
}
void signalHandler(int signum)
{
std::cout<<"Inttrrupt signal(" << signum <<") received."<<std::endl;
//清理关闭 终止程序
exit(signum);
}
// void test()
// {
// Staff * worker = NULL;
// worker = new Employee(1, "张三", 1);
// worker->showInfo();
// delete worker;
// worker = new Manager(2, "李四", 2);
// worker->showInfo();
// delete worker;
// worker = new Boss(3, "王五", 3);
// worker->showInfo();
// delete worker;
// }
int main()
{
// test();
//注册信号 SIGINT 和信号处理程序
signal(SIGINT, signalHandler);
SMS ws;
int choice = 0;
while (true)
{
//展示菜单
ws.showMenu();
cout << "请输入您的选择:" << endl;
cin >> choice;
switch (choice)
{
case 0: //退出系统
ws.exitSystem();
break;
case 1: //添加职工
ws.Add_Emp();
break;
case 2: //显示职工
ws.Disp_Emp();
break;
case 3: //删除职工
ws.Del_Emp();
break;
case 4: //查找职工
ws.Find_Emp();
break;
case 5: //修改职工
ws.Mod_Emp();
break;
case 6: //排序职工
ws.Sort_Emp();
break;
case 7: //清空文件
ws.Clear_Emp();
break;
default:
system("cls");
break;
}
}
clear();
return 0;
}
职工系统类
#pragma once
#include<iostream>
#include<string>
#include<fstream>
#include "Staff.h"
#include "employee.h"
#include "boss.h"
#include "manager.h"
const std::string FILENAME="staff.txt";
extern void clear();
class SMS
{
private:
//员工数组的 指针
Staff** m_EmpArray;
//记录文件中的人数个数
int m_EmpNum;
// 标志职工文件是否为空
bool m_FileisEmpty;
public:
SMS(/* args */){
std::ifstream ifs;
ifs.open(FILENAME, std::ios::in);
// 文件不存在时
if (!ifs.is_open())
{
std::cout<<"文件不存在" << std::endl;
m_EmpNum = 0;
m_EmpArray = nullptr;
m_FileisEmpty = true;
ifs.close();
return;
}
// 文件存在为空时
char ch;
ifs >> ch;
if (ifs.eof())
{
std::cout<<"文件为空"<<std::endl;
m_EmpNum = 0;
m_EmpArray = nullptr;
m_FileisEmpty = true;
ifs.close();
return;
}
//文件存在且不为空
int num = this->get_EmpNum();
std::cout<<"职工人数为:"<<num<<std::endl;
this->m_EmpNum = num;
this->m_EmpArray = new Staff*[this->m_EmpNum];
init_Emp();
};
~SMS(){
if (this->m_EmpArray != nullptr)
{
for (size_t i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArray[i] !=nullptr)
{
delete this->m_EmpArray[i];
}
}
delete[] this->m_EmpArray;
this->m_EmpArray = nullptr;
}
};
//显示菜单
void showMenu() const;
// 退出系统
void exitSystem();
// 添加员工
void Add_Emp();
// 显示员工
void Disp_Emp() const;
// 保存文件
void Save();
// 读取文件
void Read();
// 统计文件中的人数
int get_EmpNum();
// 读取文件中员工 初始化 员工数组的 指针
void init_Emp();
// 删除职工
void Del_Emp();
// 按编号查找职工
int Find_Emp_Id(int, int begin=0);
// 按姓名查找职工
int Find_Emp_Name(std::string, int begin=0);
//修改员工
void Mod_Emp();
//查找职工
void Find_Emp();
//按职工编号排序
void Sort_Emp();
//清空文件
void Clear_Emp();
};
#include<memory>
#include "wokerSMS.h"
using namespace std;
void SMS::showMenu(/* args */)const
{
cout << "☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆" << endl;
cout << "(^_−)☆ 欢迎使用职工系统 (^_−)☆" << endl;
cout << "(^_−)☆ 0、退出管理系统 (^_−)☆" << endl;
cout << "(^_−)☆ 1、增加职工信息 (^_−)☆" << endl;
cout << "(^_−)☆ 2、显示职工信息 (^_−)☆" << endl;
cout << "(^_−)☆ 3、删除职工信息 (^_−)☆" << endl;
cout << "(^_−)☆ 4、查找职工信息 (^_−)☆" << endl;
cout << "(^_−)☆ 5、修改职工信息 (^_−)☆" << endl;
cout << "(^_−)☆ 6、按照编号排序 (^_−)☆" << endl;
cout << "(^_−)☆ 7、清空所以文档 (^_−)☆" << endl;
cout << "☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆" << endl;
cout << endl;
}
void SMS::exitSystem()
{
cout<<"欢迎下次使用"<<endl;
exit(0);
}
void SMS::Add_Emp()
{
cout<<"input num of staff to add"<<endl;
int addNum = 0;
cin >> addNum;
if (addNum > 0)
{
//开辟新空间
int newSize = this->m_EmpNum + addNum;
Staff ** newSpace = new Staff*[newSize];
//将原空间的内容放到新空间
if (this->m_EmpArray != nullptr)
{
for (size_t i = 0; i < this->m_EmpNum; i++)
{
newSpace[i] = this->m_EmpArray[i];
}
}
//添加新员工
for (size_t i = 0; i < addNum; i++)
{
int id;
string name;
int did;
cout << "请输入第 " << i + 1 << " 个新职工编号:" << endl;
while(cin >> id)
{
if (Find_Emp_Id(id)==-1)
{
break;
}
cout<<"该Id已存在,请重新输入:"<<endl;
}
cout << "请输入第 " << i + 1 << " 个新职工姓名:" << endl;
cin >> name;
cout << "请选择该职工的岗位:" << endl;
cout << "1、普通职工" << endl;
cout << "2、经理" << endl;
cout << "3、老板" << endl;
cin >> did;
Staff * addemp = nullptr;
switch (did)
{
// case 1:
// newSpace[i+this->m_EmpNum] = new Employee(id, name, 1);
// break;
// case 2:
// newSpace[i+this->m_EmpNum] = new Manager(id, name, 2);
// break;
// case 3:
// newSpace[i+this->m_EmpNum] = new Boss(id, name, 3);
// break;
case 1:
addemp = new Employee(id, name, 1);
break;
case 2:
addemp = new Manager(id, name, 2);
break;
case 3:
addemp = new Boss(id, name, 3);
break;
default:
break;
}//end switch
//将创建职工职责 ,保存到数组中
newSpace[i+this->m_EmpNum] = addemp;
}//end for
//释放原来的空间
delete[] this->m_EmpArray;
// 指针指向新空间
this->m_EmpArray = newSpace;
// 跟新员工个数
this->m_EmpNum = newSize;
// 更新职工不为空
this->m_FileisEmpty=false;
//保存到本地文件
this->Save();
// 打印提示信息
cout<<"添加完毕!"<<endl;
}//end if
else
{
cout<<"bad input"<<endl;
}
clear();
}
void SMS::Disp_Emp() const
{
if (this->m_EmpNum <=0)
{
cout<<"文件不存在或记录为空"<<endl;
clear();
return;
}
for (size_t i = 0; i < this->m_EmpNum; i++)
{
this->m_EmpArray[i]->showInfo();
}
clear();
}
void SMS::Save()
{
// ofstream saveFile(FILENAME, ios::out);
// for (size_t i = 0; i < this->m_EmpNum; i++)
// {
// saveFile <<this->m_EmpArray[i]->m_Id<<" "
// <<this->m_EmpArray[i]->m_Name<<" "
// <<this->m_EmpArray[i]->m_DeptId<<endl;
// }
// saveFile.close();
ofstream ofs;
ofs.open(FILENAME, ios::out);
for (int i = 0; i < this->m_EmpNum; i++)
{
ofs << this->m_EmpArray[i]->m_Id << " "
<< this->m_EmpArray[i]->m_Name << " "
<< this->m_EmpArray[i]->m_DeptId << endl;
}
ofs.close();
}
int SMS::get_EmpNum()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int did;
int num = 0;
while (ifs >>id && ifs>>name && ifs>>did)
{
++num;
}
ifs.close();
return num;
}
void SMS::init_Emp()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int did;
int num = 0;
while (ifs >>id && ifs>>name && ifs>>did)
{
Staff * staff = nullptr;
if (did == 1)
{
staff = new Employee(id, name, 1);
}
else if (did == 2)
{
staff = new Manager(id, name, 2);
}
else
{
staff = new Boss(id, name, 3);
}
this->m_EmpArray[num]=staff;
++num;
}
ifs.close();
}
void SMS::Del_Emp()
{
cout<<"输入删除员工的工号:";
int del_id,index;
cin>>del_id;
if (this->m_EmpNum==0)
{
cout<<"职工数量为0,无法删除"<<endl;
return;
}
index = Find_Emp_Id(del_id);
if (index == -1)
{
cout<<"无该编号的员工,无法删除"<<endl;
return;
}
for (size_t i = index; i < this->m_EmpNum; i++)
{
this->m_EmpArray[i]=this->m_EmpArray[i+1];
}
this->m_EmpNum--;
clear();
}
int SMS::Find_Emp_Id(int id, int begin)
{
for (size_t i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArray[i]->m_Id == id)
{
return i;
}
}
return -1;
}
int SMS::Find_Emp_Name(string name, int begin)
{
for (size_t i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArray[i]->m_Name == name)
{
return i;
}
}
return -1;
}
void SMS::Mod_Emp()
{
if (this->m_FileisEmpty)
{
cout<< "文件不存在或记录为空!" << endl;
}
else
{
cout<< "请输入修改的编号:"<< endl;
int id;
cin >> id;
int index = this->Find_Emp_Id(id);
if (index!=-1)
{
cout<<"查到该员工的信息:"<<endl;
this->m_EmpArray[index]->showInfo();
delete this->m_EmpArray[index];
this->m_EmpArray[index] = nullptr;
int id=0;
string name="";
int did=0;
cout << "请输入修改后的职工编号:" << endl;
cin >> id;
cout << "请输入修改后的姓名:" << endl;
cin >> name;
cout << "请选择修改后的岗位:" << endl;
cout << "1、普通职工" << endl;
cout << "2、经理" << endl;
cout << "3、老板" << endl;
cin >> did;
Staff * addemp = nullptr;
switch (did)
{
case 1:
addemp = new Employee(id, name, 1);
break;
case 2:
addemp = new Manager(id, name, 2);
break;
case 3:
addemp = new Boss(id, name, 3);
break;
default:
break;
}//end switch
//将修改的职工 ,保存到数组中
this->m_EmpArray[index] = addemp;
// 保存到文件中
this->Save();
cout<<"修改完成~"<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
}
clear();
}
void SMS::Find_Emp()
{
if (this->m_FileisEmpty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout << "请输入查找的方式:" << endl;
cout << "1、按职工编号查找" << endl;
cout << "2、按姓名查找" << endl;
int select = 0;
cin >> select;
if (select == 1) //按职工号查找
{
int id;
cout << "请输入查找的职工编号:" << endl;
cin >> id;
int ret = Find_Emp_Id(id);
if (ret != -1)
{
cout << "查找成功!该职工信息如下:" << endl;
this->m_EmpArray[ret]->showInfo();
}
else
{
cout << "查找失败,查无此人" << endl;
}
}
else if (select == 2) //按职工号查找
{
string name;
cout << "请输入查找的职工编号:" << endl;
cin >> name;
int ret = Find_Emp_Name(name);
if (ret != -1)
{
cout << "查找成功!该职工信息如下:" << endl;
this->m_EmpArray[ret]->showInfo();
}
else
{
cout << "查找失败,查无此人" << endl;
}
}
else
{
cout << "输入选项有误" << endl;
}
}
clear();
}
void SMS::Sort_Emp()
{
if (this->m_FileisEmpty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout<<"请输入排序方式:"<<endl;
cout<<"1:按职工进行升序"<<endl;
cout<<"2:按职工进行升降序"<<endl;
int select =0;
cin >> select;
for (size_t i = 0; i < this->m_EmpNum-1; i++)
{
for (size_t j = 0; j < this->m_EmpNum-1-i; j++)
{
if (select==1)
{
//升序
if (this->m_EmpArray[j]->m_Id > this->m_EmpArray[j+1]->m_Id)
{
Staff * temp = m_EmpArray[j];
m_EmpArray[j] = m_EmpArray[j+1];
m_EmpArray[j+1] = temp;
}
}
else //if (select==2)
{
//jiang序
if (this->m_EmpArray[j]->m_Id < this->m_EmpArray[j+1]->m_Id)
{
Staff * temp = m_EmpArray[j];
m_EmpArray[j] = m_EmpArray[j+1];
m_EmpArray[j+1] = temp;
}
}
}
}
cout<< "排序后为:"<<endl;
Save();
this->Disp_Emp();
}
}
void SMS::Clear_Emp()
{
if (this->m_FileisEmpty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout<<"请确认是否删除:(y/n)"<<endl;
char choice;
cin>>choice;
if (choice='y')
{
// 打开模式 ios::trunc 如果存在 删除文件并重新创建
ofstream ofs(FILENAME, ios::trunc);
ofs.close();
if (this->m_EmpArray != nullptr)
{
for (size_t i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArray[i] != nullptr)
{
delete this->m_EmpArray[i];
}
}
this->m_EmpNum = 0;
delete[] this->m_EmpArray;
this->m_FileisEmpty = true;
this->m_EmpArray = nullptr;
}
cout<<"清空成功!";
}
}
clear();
}
职工类
#pragma once
#include<iostream>
#include<string>
#include<fstream>
class Staff
{
private:
/* data */
public:
Staff(/* args */){
std::cout<<"Staff()"<<std::endl;
};
virtual ~Staff(){
std::cout<<"~Staff()"<<std::endl;
};
int m_Id; //职工编号
std::string m_Name; //职工姓名
int m_DeptId;
//显示个人信息
virtual void showInfo() = 0;
//返回岗位信息
virtual std::string getDeptName() = 0;
};
普通职工类
#pragma once
#include "Staff.h"
class Employee :public Staff
{
private:
/* data */
public:
Employee(int id=0, std::string name=" ", int did=0){
m_Id=id;
m_Name = name;
m_DeptId = did;
std::cout<<"Employee()"<<std::endl;
}
~Employee(){
std::cout<<"~Employee()"<<std::endl;
};
void showInfo() override
{
std::cout<<"职工编号:"<<m_Id
<<"\t姓名:"<<m_Name
<<"\t岗位:"<<getDeptName()
<<"\t岗位职责:完成上级交给的任务"<<std::endl;
}
std::string getDeptName() override
{
return std::string("员工");
}
};
经理类
#pragma once
#include "Staff.h"
class Manager :public Staff
{
private:
/* data */
public:
Manager(int id=0, std::string name=" ", int did=0){
m_Id=id;
m_Name = name;
m_DeptId = did;
std::cout<<"Manager()"<<std::endl;
}
~Manager(){
std::cout<<"~Manager()"<<std::endl;
};
void showInfo() override
{
std::cout<<"职工编号:"<<m_Id
<<"\t姓名:"<<m_Name
<<"\t岗位:"<<getDeptName()
<<"\t岗位职责:完成老板交给的任务,给员工派任务。"<<std::endl;
}
std::string getDeptName() override
{
return std::string("经理");
}
};
老板类
#pragma once
#include "Staff.h"
class Boss :public Staff
{
private:
/* data */
public:
Boss(int id=0, std::string name=" ", int did=0){
m_Id=id;
m_Name = name;
m_DeptId = did;
std::cout<<"Boss()"<<std::endl;
}
~Boss(){
std::cout<<"~Boss()"<<std::endl;
};
void showInfo() override
{
std::cout<<"职工编号:"<<m_Id
<<"\t姓名:"<<m_Name
<<"\t岗位:"<<getDeptName()
<<"\t岗位职责:管理公司事务。"<<std::endl;
}
std::string getDeptName() override
{
return std::string("老板");
}
};
总结
1、职工数据 用职工类Staff的指针数组存储,可以存自己或子类的指针,直接用“this->m_EmpArray[i]->showInfo();”实现多态;加override显示该成员函数为重写的
2、使用指针数组练习指针操作、new、delete等;new一个指针数组Staff ** newSpace = new Staff*[newSize];
3、读取TXT的一种方法
4、代码交互的地方较多,输入校验过少。
5、增加信号处理 signal(SIGINT, signalHandler);(捕获到Ctrl+C终止程序)。
6、增加预编译,判断运行环境。