A project takes you into object-oriented programming: C + + implementation of employee management system

preface

object-oriented It is a very common programming idea. Through a practical project, this paper will take you into object-oriented and experience the application of object-oriented in practical development, which brings us convenience.

The project of this paper comes from Dark horse programmer An example in a series of courses. This paper will analyze and implement the example by the author, show you the three characteristics of object-oriented, and include the vast majority of knowledge points in object-oriented as far as possible, hoping to be helpful to you.

Don't gossip. Let's enter the project example now. Let's start!

1, Project overview

This time, an employee management operating system is developed, which can realize the orderly management of employee information, including common operations such as addition, deletion, modification, query and arrangement. At the same time, the code should have good perfection, robustness and scalability, the memory allocation should be rigorous and reasonable, and effectively respond to illegal operations and unreasonable input of the user. In short, It should be a robust management system.

The difficulty of the project mainly lies in how to use object-oriented knowledge to realize the functions required by the topic:

First of all, we need to implement these functions to complete the corresponding operations on the employee information container, such as adding, deleting, modifying and querying. Similar operations have been in Address book management system It has been implemented in, but its processing method is based on the structure array, so there are also problems such as limited capacity and complex operation. The number of times, the author plans to use the array container provided by C + + to store employee information and use the iterator to operate the array elements, so as to simplify the code and improve the readability of the code.

Secondly, what data type do we use to store employee related information? Each employee's information includes name, number, position, salary and other information. To integrate these information, it is not difficult for us to think of using "class" to realize it, but how to realize the so-called "Employee class"? How to implement his correlation function? How to implement object-oriented thinking?

The overall architecture is clear, so how to solve the above two problems?

2, Project details

1. Implementation of Staff

First of all, we can make full use of the three basic features of Staff oriented program: Staff and protected. In order to fully realize the security of Staff oriented program, we can set the three basic features of Staff oriented program: Staff and protected, Avoid unintentional modification while ensuring subclass inheritance. So, how do we get and set the values of these three data?

Here we will use the first object-oriented feature: encapsulation . We provide an interface for setting and modifying these three attributes through member functions to facilitate operation.

The Worker base class is declared as follows:

/* Alkaid#3529 */

class worker
{
public:
	//Provide external interfaces for obtaining and changing private properties
	void set_name(string name);

	string get_name();

	void set_id(string id);

	string get_id();

	void set_post(string post);

	string get_post();

	//Pure virtual destruct, which releases the data opened up in the heap area in the subclass
	virtual ~worker() = 0;

protected:
	string m_name;
	string m_id;
	string m_post;

};

The Worker base class is implemented as follows:

/* Alkaid#3529 */

//Provide external interfaces for obtaining and changing private properties
void worker::set_name(string name)
{
	this->m_name = name;
}

string worker::get_name()
{
	return this->m_name;
}

void worker::set_id(string id)
{
	this->m_id = id;
}

string worker::get_id()
{
	return this->m_id;
}

void worker::set_post(string post)
{
	this->m_post = post;
}

string worker::get_post()
{
	return this->m_post;
}

worker::~worker() {}

Careful readers may find that we set the destructor of the Worker base class as a virtual function. What's the use of this writing?

After implementing the base class, we begin to write the Staff derived class, that is, the class we will eventually use, use it to inherit the prepared Worker base class, and add a data, salary. In particular, we open up the salary value in the heap area.

The code declaration of Staff derived class is as follows:

class staff :public worker
{
public:

	//Parametric construction, add default parameters to be compatible with nonparametric construction
	//Add explicit keyword to eliminate implicit conversion
	explicit staff(string name = " ", string id = "000000", string post = "Employee", int salary = 500);

	//Copy structure, even if not used, must be rewritten to solve potential problems
	explicit staff(staff& s);

	//Rewrite the destructor to correctly release the data opened up in the heap
	~staff();


	//Provide external interface to obtain and modify salary value
	void set_salary(int salary);

	int get_salary();


	//Operator overloading 

	//Shift left operator overload, directly output the worker's name, number, position and salary
	friend ostream& operator<<(ostream& cout, staff& s);

	//Shift right operator overload to simplify the code of reading employee information in the later stage
	friend istream& operator>>(istream& cin, staff& s);

	//The assignment operator is overloaded to facilitate mutual assignment between classes
	staff& operator=(staff& s);

	//Relational operator overload, used for post sort
	bool operator<(staff& s);

private:
	//Set the integer pointer to the integer variable opened in the heap
	int* m_salary;
};

First of all, we declare his constructor in the Staff derived class, including parameter construction and copy construction, and implement his fictitious functions. It needs to be specially declared here: because the subclass Staff has data opened in the heap, when the reference of the parent class points to the object of the child class, the parent class destructor will not completely release the data opened in the heap by the child class, It leads to memory leakage and potential security risks. Therefore, it is necessary to declare the destructor of the parent class as a pure virtual function, so that the subclass must rewrite the destructor of the parent class to ensure the safety of heap data.

Secondly, it is the implementation of subclass copy construction. Due to the existence of heap data in subclasses, the problem of deep and shallow copy arises. Ordinary copy is a shallow copy. In the copy process, it is only a simple copy of data, which is easy to produce address shallow copy and the repeated release of heap data. Therefore, it is necessary to consider the copy structure and solve the problem of deep and shallow copy.

Finally, we declare a series of overloaded operators of the Staff derived class. In order to simplify the subsequent code, I choose to overload the operators here, so as to reduce the code complexity of the subsequent read in and output data.

The code implementation of Staff derived class is as follows:

//Parametric construction, add default parameters to be compatible with nonparametric construction
staff::staff(string name, string id, string post, int salary)
{

	this->m_name = name;
	this->m_id = id;
	this->m_post = post;

	//Opening up space in the heap to store salary values brings problems related to deep and shallow copies and destructors
	this->m_salary = new int(salary);
}

//Copy structure, even if not used, must be rewritten to solve potential problems
staff::staff(staff& s)
{
	this->m_name = s.m_name;
	this->m_id = s.m_id;
	this->m_post = s.m_post;

	//Deep copy, otherwise only the pointer address will be copied
	*this->m_salary = *s.m_salary;
}

//Rewrite the destructor to correctly release the data opened up in the heap
staff::~staff()
{
	//Make sure the pointer is not empty before releasing
	if (m_salary != NULL)
	{
		delete m_salary;
		m_salary = NULL;
	}
}

//Provide external interface to obtain and modify salary value
void staff::set_salary(int salary)
{
	*this->m_salary = salary;
}

int staff::get_salary()
{
	return *m_salary;
}

//The assignment operator is overloaded to facilitate mutual assignment between classes
staff& staff::operator=(staff& s)
{
	this->set_name(s.m_name);
	this->set_id(s.m_id);
	this->set_post(s.m_post);
	this->set_salary(*s.m_salary);

	return *this;
}

//Relational operator overload, used for post sort
bool staff::operator<(staff& s)
{
	if (this->m_id < s.m_id)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

ostream& operator<<(ostream& cout, staff& s)
{
	cout << "Name : " << s.m_name;

	for (unsigned int i = 0; i < 13 - s.m_name.length(); i++)
	{
		cout << " ";
	}

	cout << "ID : " << s.m_id << "    Post : " << s.m_post;

	return cout;
}

istream& operator>>(istream& cin, staff& s)
{
	cout << "Please enter employee name:";
	while (1)
	{
		cin >> s.m_name;

		if (s.m_name.length() > 13)
		{
			cout << "The name exceeds the specified length, please re-enter:";
		}
		else
		{
			break;
		}
	}

	cout << "Please enter employee position( Boss, Manager, Employee): ";
	while (1)
	{
		cin >> s.m_post;

		string str_Boss = "Boss";
		string str_Manager = "Manager";
		string str_Employee = "Employee";

		if (s.m_post == str_Boss || s.m_post == str_Manager || s.m_post == str_Employee)
		{
			break;
		}
		else
		{
			cout << "There is no such position, please re-enter:";
		}
	}

	cout << "Please enter the employee number (six digits, such as 00000 1):";
	while (1)
	{
		cin >> s.m_id;

		if (s.m_id.length() < 6)
		{
			cout << "The number is not long enough, please re-enter:";
			continue;
		}
		else if (s.m_id.length() > 6)
		{
			cout << "The number length is too long, please re-enter:";
			continue;
		}

		int i = 0;
		while (i < s.m_id.length())
		{
			if (!(s.m_id[i] >= '0' && s.m_id[i] <= '9'))
			{
				break;
			}
			i++;
		}

		if (i != 6)
		{
			cout << "The number must be composed of pure numbers and does not contain special characters. Please re-enter:";
		}
		else
		{
			break;
		}
		
	}

	return cin;
}

It is worth mentioning that in order to deal with the possible illegal input of users, the author specially added error handling in the reading process to prompt the wrong input of users to ensure the smooth operation of the code.

At this point, we have completed the first major task, the implementation of classes. Next, we are nonstop to realize the overall architecture of the system.

2. System architecture implementation

The system involves many functions. Here, the author chooses to implement the corresponding functions for each function. First, let's take a look at the overall architecture.

The architecture code is as follows:

/* Alkaid#3529 */

// The menu function displays the system menu for the user to select, and enters the corresponding function according to the function selected by the user
void menu(vector<staff*>& s);

// Locate the location of the corresponding element according to the specified conditions
int Locate_staff(vector<staff*>& s, string clue);

// key == 1 new employee
void Add_staff(vector<staff*>& s);

// key == 2 display employee
void Display_staff(vector<staff*>& s);

// key == 3 find and display employee information
void Find_staff(vector<staff*>& s);

// key == 4 modify employee information
void Revise_staff(vector<staff*>& s);

// key == 5 delete employee information
void Remove_staff(vector<staff*>& s);

// key == 6 sort employee information
void Sort_staff(vector<staff*>& s);

// key == 7 empty employee
void Empty_staff(vector<staff*>& s);

// Swap two elements at a specified location
void swap(vector<staff*>& s, int index1, int index2);

After implementing the Staff subclass, I chose to use the vector container to store employee information, but a large amount of employee information will lead to excessive data processing in the subsequent function implementation. Therefore, we wondered whether we could choose a more efficient and convenient storage method?

Yes, it's the pointer!

The pointers of each Staff object are stored together in the vector container, and each pointer maintains a Staff object. In this way, it becomes extremely simple to exchange container elements or delete elements later.

First, we create the entrance of the whole system:

/* Alkaid#3529 */

#include"head.h"

int main()
{
	vector<staff*>s;

	menu(s);

	return 0;
}

We use a menu function as a guide to realize the printing system interface, function selection and other operations in the menu function:

void menu(vector<staff*>& s)
{
	int key = 0;

	while (1)
	{
		cout << "Welcome to by Alkaid#3529 development of the staff management system, the system provides the following functions: "< endl;
		cout << "1. New employee information" << endl;
		cout << "2. Show all employees" << endl;
		cout << "3. Find employee information" << endl;
		cout << "4. Modify employee information" << endl;
		cout << "5. Delete employee information" << endl;
		cout << "6. System sort" << endl;
		cout << "7. Empty management system" << endl;
		cout << "0. Exit management system" << endl;

		cout << "Please select the function you need (with the number 0) - 7 Representation:";

		// Read in key
		while (1)
		{
			cin >> key;

			if (cin.fail() || key < 0 || key>7)
			{
				cin.clear();
				cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

				cout << "Your input is incorrect, please re-enter (with the number 0) - 7 Representation:";
			}
			else
			{
				break;
			}
		}
		cout << endl;

		if (key == 1)
		{
			Add_staff(s);
		}
		else if (key == 2)
		{
			Display_staff(s);
		}
		else if (key == 3)
		{
			Find_staff(s);
		}
		else if (key == 4)
		{
			Revise_staff(s);
		}
		else if (key == 5)
		{
			Remove_staff(s);
		}
		else if (key == 6)
		{
			Sort_staff(s);
		}
		else if (key == 7)
		{
			Empty_staff(s);
		}
		else if (key == 0)
		{
			cout << endl << "The system has exited" << endl;
			break;
		}

		system("pause");
		system("cls");
	}

}

Cycle the print selection interface and read in the function selected by the user. At the same time, process and judge the user's function selection input. If the user inputs correctly, enter the corresponding function.

The first is the new employee function:

void Add_staff(vector<staff*>& s)
{
	staff* s_temp = new (staff);

	cin >> *s_temp;

	s.push_back(s_temp);

	cout << endl << "Successfully added employee information,";

}

It is worth mentioning that here we choose to use new to apply for space from the heap area to create employees. When deleting employees, we should pay attention to the release of heap area space.

Next is the function function to display the information of all employees. Because we have overloaded the shift right operator in the class, we can output it directly:

void Display_staff(vector<staff*>& s)
{
	for (int i = 0; i < s.size(); i++)
	{
		cout << *s[i] << endl;
	}
	cout << endl;

}

Before the implementation of subsequent functions, it is necessary to implement a function function to find employees, so as to provide the basis for a series of subsequent functions. The function function is to find the corresponding index according to the employee's name or number and return it. Otherwise, it returns - 1:

int Locate_staff(vector<staff*>& s, string clue)
{
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i]->get_name() == clue)
		{
			return i;
		}
	}

	for (int i = 0; i < s.size(); i++)
	{
		if (s[i]->get_id() == clue)
		{
			return i;
		}
	}

	return -1;
}

The next step is to realize the simple function of adding, deleting, modifying and querying. There is nothing new:

void Find_staff(vector<staff*>& s)
{
	cout << "Please enter the name or number of the employee you are looking for:";
	string clue = "";
	cin >> clue;
	cout << endl;

	int pos = Locate_staff(s, clue);

	if (pos == -1)
	{
		cout << "Sorry, no search results" << endl << endl;
	}
	else
	{
		cout << *s[pos] << endl << endl;
	}

}

void Revise_staff(vector<staff*>& s)
{
	cout << "Please enter the name or number of the employee you want to modify:";
	string clue = "";
	cin >> clue;
	cout << endl;

	int pos = Locate_staff(s, clue);

	if (pos == -1)
	{
		cout << "Sorry, no search results" << endl << endl;
		return;
	}

	cout << *s[pos] << endl << endl;

	staff* s_temp = new(staff);
	cin >> *s_temp;

	delete s[pos];
	s[pos] = s_temp;

	cout << endl << "Successfully modified,";
}

void Remove_staff(vector<staff*>& s)
{
	cout << "Please enter the name or number of the employee you want to delete:";
	string clue = "";
	cin >> clue;
	cout << endl;

	int pos = Locate_staff(s, clue);

	if (pos == -1)
	{
		cout << "Sorry, no search results" << endl << endl;
		return;
	}

	delete s[pos];

	s.erase(s.begin() + pos);

	cout << "Deleted successfully,";
}

For the convenience of the author, I might as well choose another sorting algorithm for the employees Beauty of algorithm , I will make my own opinions on various algorithms, which will not be repeated here:

void Sort_staff(vector<staff*>& s)
{
	cout << "Please select collation (0) - Ascending order, 1 - (descending):";

	string str_0 = "0";
	string str_1 = "1";

	string str_k = "0";

	while (1)
	{
		cin >> str_k;

		if (str_k != str_0 && str_k != str_1)
		{
			cout << "Error in input, please re-enter:";
		}
		else
		{
			break;
		}
	}

	if (str_k == str_0)
	{
		for (int i = 0; i < s.size(); i++)
		{
			int min = i;
			for (int j = i + 1; j < s.size(); j++)
			{
				if (*s[j] < *s[min])
				{
					min = j;
				}
			}
			if (i != min)
			{
				swap(s, i, min);
			}
		}
	}
	else
	{
		for (int i = 0; i < s.size(); i++)
		{
			int max = i;
			for (int j = i + 1; j < s.size(); j++)
			{
				if (*s[max] < *s[j])
				{
					max = j;
				}
			}
			if (i != max)
			{
				swap(s, i, max);
			}
		}
	}

	cout << endl << "Sorting is complete,";

}

When emptying the container, it should be noted that not only empty the container, but first release the space in the heap area pointed by the pointer in the container. If it is only clear, it will lead to the fatal problem of memory leakage. In the follow-up, the author will also elaborate on such related problems in detail:

void Empty_staff(vector<staff*>& s)
{

	// Release the pointer to the space one by one
	for (int i = 0; i < s.size(); i++)
	{
		delete s[i];
	}

	// Empty the data stored in the container
	s.clear();
}

So far, the idea of the whole project has been explained. The author of the whole project tries to integrate the relevant knowledge of object-oriented, such as encapsulation, inheritance, polymorphism, virtual function, pure virtual destructor, operator overloading, etc., but the author's ability is limited, and the complete source code is here Employee management system , shortcomings, welcome to correct.

summary

There are still many details of object-oriented that can only be obtained through practice. This project can only be used as an exercise for your reference and trial. Of course, there are many disadvantages to be solved in project design. It is limited by this level, but it still pursues progress!

We will continue to update new C + + projects in the future. Welcome to subscribe to my channel. See you next time.

Keywords: C++ Back-end

Added by stuartbates on Thu, 03 Mar 2022 20:06:59 +0200