C++抽象类对象创建及员工管理类实现问题求助
Hey there! Let's tackle your two questions one by one, and fix that frustrating "cannot create abstract class object" error you're running into with your code.
Short answer: No, you can't directly create an object of an abstract class. This is intentional—abstract classes are designed to define a common interface that derived classes must implement, not to be instantiated on their own. The presence of at least one pure virtual function (like your virtual void print()=0;) marks the class as abstract.
Instead, you work with pointers or references to the abstract class type. These pointers/references can point to objects of concrete derived classes (classes that implement all pure virtual functions from the abstract base). This is how polymorphism works in C++—it lets you treat all employee types the same way while still calling their specific behaviors.
Let's break down why you're getting that error first, then walk through a corrected version of your code:
Why your current code fails:
- Your
PermanentEmployeeandContractualEmployeeclasses don't implement the pure virtualprint()function fromEmployee. That makes them abstract classes too—so you can't create objects of them either! - You tried to declare
PermanentEmployee PE;without a default constructor (yourPermanentEmployeeonly has a parameterized constructor). PermanentEmployeeusesprotectedinheritance, which breaks the "is-a" relationship withEmployee—you won't be able to use it where anEmployee*is expected, which defeats the purpose of polymorphism for your company's employee list.- Your
Employeeconstructor is declared but not implemented, which would cause a linker error later. - The
Companyclass'slistis a raw pointer, which isn't flexible enough to store an arbitrary number of employees.
Corrected Code
#include<iostream> #include<string> #include<vector> // For dynamic, resizable employee storage using namespace std; struct dob { int date, month, year; }; // Fixed typo: "day" -> "month" (likely a mistake) class Employee { public: string Name; int ID; string Department; double MonthlyGrossSalary; double MonthlyNetSalary; // Implement the base class constructor Employee(string name, int id, string dep, double mgs, double mns) : Name(name), ID(id), Department(dep), MonthlyGrossSalary(mgs), MonthlyNetSalary(mns) {} // Empty implementations for now (you can expand these later) virtual void CalculateAnnualIncomeTax() {} virtual void CalculateMonthlyIncomeTax() {} virtual void print() = 0; // Pure virtual function - MUST be implemented by derived classes }; // Use public inheritance to maintain "is-a Employee" relationship class PermanentEmployee : public Employee { public: double ProvidentFund; double AnnualMedicalInsuranceLimit; PermanentEmployee(double pf, double amil, string name, int id, string dep, double mgs, double mns) : Employee(name, id, dep, mgs, mns), ProvidentFund(pf), AnnualMedicalInsuranceLimit(amil) {} // Implement the pure virtual print function void print() override { cout << "Permanent Employee Details:\n"; cout << "Name: " << Name << "\nID: " << ID << "\nDepartment: " << Department << "\n"; cout << "Gross Salary: " << MonthlyGrossSalary << "\nNet Salary: " << MonthlyNetSalary << "\n"; cout << "Provident Fund: " << ProvidentFund << "\nMedical Limit: " << AnnualMedicalInsuranceLimit << "\n"; } }; class ContractualEmployee : public Employee { public: dob ContractStartDate; dob ContractEndDate; ContractualEmployee(dob csd, dob ced, string name, int id, string dep, double mgs, double mns) : Employee(name, id, dep, mgs, mns), ContractStartDate(csd), ContractEndDate(ced) {} // Implement the pure virtual print function void print() override { cout << "Contractual Employee Details:\n"; cout << "Name: " << Name << "\nID: " << ID << "\nDepartment: " << Department << "\n"; cout << "Gross Salary: " << MonthlyGrossSalary << "\nNet Salary: " << MonthlyNetSalary << "\n"; cout << "Contract Start: " << ContractStartDate.date << "/" << ContractStartDate.month << "/" << ContractStartDate.year << "\n"; cout << "Contract End: " << ContractEndDate.date << "/" << ContractEndDate.month << "/" << ContractEndDate.year << "\n"; } }; class Company { private: vector<Employee*> employees; // Dynamic list to store any number of employees public: // Add a new employee to the company void AddEmployee(Employee* emp) { employees.push_back(emp); } // Print details of all employees in the company void PrintAllEmployees() { for (auto emp : employees) { emp->print(); cout << "-------------------------\n"; } } // Clean up dynamically allocated memory to avoid leaks ~Company() { for (auto emp : employees) { delete emp; } } }; void datainput(string&, int&, string&, double&, double&); void getContractDates(dob&, dob&); int main() { char option; string name; string dep; int id; double mgs; double mns; Company myCompany; do { cout << "\nSelect Type of Employee\n"; cout << "Permanent Employee [P][p]\n"; cout << "Contractual Employee [C][c]\n"; cout << "Quit & Print All [Q][q]\n"; cout << "Enter your choice: "; cin >> option; switch(option) { case 'P': case 'p': { datainput(name, id, dep, mgs, mns); double pf, amil; cout << "Enter Provident Fund: "; cin >> pf; cout << "Enter Annual Medical Insurance Limit: "; cin >> amil; // Create employee dynamically and add to company myCompany.AddEmployee(new PermanentEmployee(pf, amil, name, id, dep, mgs, mns)); cout << "Permanent employee added!\n"; break; } case 'C': case 'c': { datainput(name, id, dep, mgs, mns); dob start, end; getContractDates(start, end); // Create employee dynamically and add to company myCompany.AddEmployee(new ContractualEmployee(start, end, name, id, dep, mgs, mns)); cout << "Contractual employee added!\n"; break; } case 'Q': case 'q': cout << "\n--- All Company Employees ---\n"; myCompany.PrintAllEmployees(); break; default: cout << "Invalid option! Try again.\n"; } } while (option != 'Q' && option != 'q'); return 0; } void datainput(string& n, int& no, string& d, double& mg, double& mn) { cout << "\nEnter Employee Data\n"; cout << "Name: "; cin >> n; cout << "ID: "; cin >> no; cout << "Department: "; cin >> d; cout << "Monthly Gross Salary: "; cin >> mg; cout << "Monthly Net Salary: "; cin >> mn; } void getContractDates(dob& start, dob& end) { cout << "\nEnter Contract Start Date (date month year): "; cin >> start.date >> start.month >> start.year; cout << "Enter Contract End Date (date month year): "; cin >> end.date >> end.month >> end.year; }
Key changes made:
- Implemented pure virtual
print(): Both derived classes now have their ownprint()implementation, making them concrete (non-abstract) classes that can be instantiated. - Public inheritance:
PermanentEmployeenow uses public inheritance, so it's properly recognized as anEmployeetype for polymorphism. - Dynamic storage with
std::vector: TheCompanyclass usesvector<Employee*>to store any number of employees, which is flexible and safe. - Dynamic object creation: Employees are created with
new(and cleaned up in theCompanydestructor) so they can be stored asEmployee*pointers. - Added loop for multiple employees: The main function lets you add as many employees as you want until you quit, then prints all of them.
内容的提问来源于stack exchange,提问作者Rimsha Nasir

