C++ Staff Management: Inheritance and Polymorphism
Classified in Computers
Written on in English with a size of 10.44 KB
C++ Staff Management System: Inheritance and Polymorphism
This document presents a refactored C++ program demonstrating object-oriented principles such as inheritance and polymorphism. The system models a basic staff management application, featuring a base Officer
class and derived classes for specific roles like JusticeOfficer
and Firefighter
. It highlights dynamic memory management, virtual functions, and runtime polymorphism.
Core Concepts Illustrated
- Inheritance:
JusticeOfficer
andFirefighter
inherit from the baseOfficer
class. - Polymorphism: Virtual functions (
insert()
,show()
, destructor) allow for different behaviors based on the actual object type at runtime. - Dynamic Memory: Usage of
new
anddelete[]
for character arrays (DNI, names) and object instances. - Constructors & Destructors: Proper initialization and cleanup of resources.
Corrected C++ Code Implementation
The original code contained several syntax, naming, and logical errors. The following sections present the corrected and improved C++ code, organized for clarity and adherence to modern C++ practices.
1. Header Files and Namespace
Standard C++ headers are used, and std::
prefix is explicitly added for cout
, cin
, and endl
to avoid polluting the global namespace.
#include <iostream>
#include <cstring> // For strlen and strcpy
// No using namespace std; to avoid potential conflicts
2. Base Class: Officer
The Officer
class serves as the base for all staff members. It includes common attributes like DNI (ID) and salary, along with virtual methods for inserting and displaying data, and a virtual destructor for proper cleanup in polymorphic scenarios.
class Officer {
protected:
char *dni; // Document Number Identification
double salary;
public:
// Constructor with default values
Officer(const char *pdni = "", double salary_val = 0);
// Virtual destructor for proper memory cleanup in derived classes
virtual ~Officer();
// Virtual methods for data insertion and display
virtual void insert();
virtual void show();
};
// Officer Class Method Definitions
Officer::Officer(const char *pdni, double salary_val) {
dni = new char[strlen(pdni) + 1];
strcpy(dni, pdni);
salary = salary_val;
std::cout << "Officer Constructor" << std::endl;
}
Officer::~Officer() {
delete[] dni;
std::cout << "Officer Destructor" << std::endl;
}
void Officer::insert() {
// Prevent memory leak if insert is called multiple times
if (dni) {
delete[] dni;
}
dni = new char[10]; // Assuming DNI is max 9 chars + null terminator
std::cout << "\nEnter Officer DNI: ";
std::cin >> dni;
std::cout << "Enter Officer Salary: ";
std::cin >> salary;
}
void Officer::show() {
std::cout << "\nOfficer with DNI: " << dni << std::endl;
std::cout << "and salary: " << salary << " Euros." << std::endl;
}
3. Derived Class: JusticeOfficer
The JusticeOfficer
class inherits from Officer
and adds specific attributes like monthly working hours and the name of the court. It overrides the insert()
and show()
methods to handle its unique data.
class JusticeOfficer : public Officer {
protected:
int monthlyHours;
char *courtName; // Name of the court
public:
// Constructor with default values, calling base class constructor
JusticeOfficer(int monthlyHours_val = 0, const char *courtName_val = "", const char *dni_val = "", double salary_val = 0);
// Destructor for JusticeOfficer specific cleanup
~JusticeOfficer();
// Overridden methods for data insertion and display
void insert() override;
void show() override;
};
// JusticeOfficer Class Method Definitions
JusticeOfficer::JusticeOfficer(int monthlyHours_val, const char *courtName_val, const char *dni_val, double salary_val)
: Officer(dni_val, salary_val) {
courtName = new char[strlen(courtName_val) + 1];
strcpy(courtName, courtName_val);
monthlyHours = monthlyHours_val;
std::cout << "JusticeOfficer Constructor" << std::endl;
}
JusticeOfficer::~JusticeOfficer() {
delete[] courtName;
std::cout << "JusticeOfficer Destructor" << std::endl;
}
void JusticeOfficer::insert() {
// Call base class insert to get DNI and salary
Officer::insert();
// Prevent memory leak if insert is called multiple times
if (courtName) {
delete[] courtName;
}
courtName = new char[30]; // Assuming court name is max 29 chars + null terminator
std::cout << "Enter number of hours worked per month: ";
std::cin >> monthlyHours;
std::cout << "Enter the name of the city court: ";
std::cin >> courtName;
}
void JusticeOfficer::show() {
Officer::show(); // Call base class show for common data
std::cout << "Working " << monthlyHours << " hours per month" << std::endl;
std::cout << "in the courts of " << courtName << "." << std::endl;
}
4. Derived Class: Firefighter
The Firefighter
class also inherits from Officer
, adding attributes for the assigned district and promotion year. It provides its own implementations for insert()
and show()
.
class Firefighter : public Officer {
protected:
char *districtName;
int promotionYear;
public:
// Constructor with default values, calling base class constructor
Firefighter(const char *districtName_val = "", int promotionYear_val = 0, const char *dni_val = "", double salary_val = 0);
// Destructor for Firefighter specific cleanup
~Firefighter();
// Overridden methods for data insertion and display
void insert() override;
void show() override;
};
// Firefighter Class Method Definitions
Firefighter::Firefighter(const char *districtName_val, int promotionYear_val, const char *dni_val, double salary_val)
: Officer(dni_val, salary_val) {
districtName = new char[strlen(districtName_val) + 1];
strcpy(districtName, districtName_val);
promotionYear = promotionYear_val;
std::cout << "Firefighter Constructor" << std::endl;
}
Firefighter::~Firefighter() {
delete[] districtName;
std::cout << "Firefighter Destructor" << std::endl;
}
void Firefighter::insert() {
// Call base class insert to get DNI and salary
Officer::insert();
// Prevent memory leak if insert is called multiple times
if (districtName) {
delete[] districtName;
}
districtName = new char[30]; // Assuming district name is max 29 chars + null terminator
std::cout << "Enter promotion year: ";
std::cin >> promotionYear;
std::cout << "Enter assigned district: ";
std::cin >> districtName;
}
void Firefighter::show() {
Officer::show(); // Call base class show for common data
std::cout << "Promotion year: " << promotionYear << std::endl;
std::cout << "Working in district: " << districtName << "." << std::endl;
}
5. Main Function: Demonstrating Polymorphism
The main
function demonstrates the use of polymorphism by creating objects of derived classes and manipulating them through base class pointers. This allows for uniform handling of different staff types.
int main(int argc, char *argv[]) {
// Create objects using base class pointers
Officer *fp1 = new Officer("11258789C", 20000);
Officer *fp2 = new JusticeOfficer(160, "Barcelona", "70546987Z", 19000);
Officer *fp3 = new Firefighter("Salamanca", 2002, "21546987B", 30000);
// Create objects with default constructors, to be filled via insert()
Officer *fp4 = new Firefighter();
Officer *fp5 = new JusticeOfficer();
Officer *fp6 = new Officer();
// Display initial data
std::cout << "\n--- Initial Data Display ---" << std::endl;
fp1->show();
fp2->show();
fp3->show();
// Insert data for default-constructed objects and then display
std::cout << "\n--- Data Insertion and Display for New Objects ---" << std::endl;
std::cout << "\n--- Inserting data for Firefighter (fp4) ---" << std::endl;
fp4->insert();
fp4->show();
std::cout << "\n--- Inserting data for JusticeOfficer (fp5) ---" << std::endl;
fp5->insert();
fp5->show();
std::cout << "\n--- Inserting data for Officer (fp6) ---" << std::endl;
fp6->insert();
fp6->show();
// Clean up dynamically allocated memory
delete fp1;
delete fp2;
delete fp3;
delete fp4;
delete fp5;
delete fp6;
return 0;
}
Key Improvements and Best Practices
- Consistent Naming: Variable names like
dni
,salary
,monthlyHours
,courtName
, andpromotionYear
are used consistently. - Memory Safety: Added
delete[]
before re-allocating memory ininsert()
methods to prevent leaks if called multiple times on the same object. const char*
for String Inputs: Ensures that string literals passed to constructors are treated as constant.override
Keyword: Explicitly marks overridden virtual functions, improving code readability and compile-time error checking.- Base Class
insert()
/show()
Calls: Derived classes now call their base class counterparts to reuse common logic. - Standard C++ Headers: Replaced old
.h
headers with modern equivalents. - Standard
main
Signature: Correctedmain
function signature toint main(int argc, char *argv[])
and addedreturn 0;
. - Clearer Output: Improved console output messages for better user experience.