dynamic polymorphism not being implemented properly in c++ - c++

i am trying to make a payroll system hierarchy and my base class of all is a abstract class and all the other classes inherited are concrete classes (classes that can be instantiated).. i have a pure virtual function earning() in my base class abstract base class employee.. the proper functionality of earning is provided in the derived classes depending on the type of employee whose earning is being calculated. I also have a virtual function in the abstract base class that is display information which is overridden in all the derived classes.
The class hierarchy goes like this
class employee;
class commissionEmployee : public employee;
class salariedEmployee : public employee;
class basePlusCommissionEmployee : public employee
the commission employee's overridden pure virtual function earning adds up the gross sales of the employee in a week with the commission rate and should return a double.
the salaried employee's overridden earning function only returns the salary that is earned by the employee as his/her salary is the only earning.
the basePlusCommissionEmployee means that a employee who has both things being added up in his/her earning function that is the salary of that employee and the commission that employee will earn from the sales he/she makes..
the problem that i a facing is that when i use a base class pointer to point at a derived class's object.. the dynamic polymorphism does get implemented but in the displayInformation function that alse overridden in each class, i do not get the total information.. it does not displays the name of the employee nor his/her earning.
i have also posted an image that shows the output of the overridden displayInformation function of the salaried employee class.. other than name and social security number the only additional input salaried employee class asks for is the salary of that employee..
#include <iostream>
#include <cstdlib>
using namespace std;
class employee
{
private:
string name;
string socialSecurityNumber;
public:
void setName(string);
string getName();
void setSSN(string);
string getSSN();
virtual double earnings() = 0;
virtual void displayInformation();
};
void employee::setName(string argName)
{
name = argName;
}
string employee::getName()
{
return name;
}
void employee::setSSN(string argSSN)
{
socialSecurityNumber = argSSN;
}
string employee::getSSN()
{
return socialSecurityNumber;
}
void employee::displayInformation()
{
cout <<"name: " <<getName()
<<"Social security number: " <<getSSN();
}
class salariedEmployee : public employee
{
private:
double salary;
public:
void setSalary(double);
double getSalary();
virtual double earnings();
virtual void displayInformation();
};
void salariedEmployee::setSalary(double argSalary)
{
salary = argSalary;
}
double salariedEmployee::getSalary()
{
return salary;
}
double salariedEmployee::earnings()
{
//we will only return salary because that is the only earning of a salaried employee
return salary;
}
void salariedEmployee::displayInformation()
{
employee::displayInformation();
cout <<"weekly salary: " <<getSalary();
}
class commissionEmployee : public employee
{
private:
double commissionRate;
double grossSales;
public:
void setCommission(double);
double getCommission();
void setGrossSales(double);
double getGrossSales();
virtual double earnings();
virtual void displayInformation();
};
void commissionEmployee::setCommission(double argCommission)
{
commissionRate = argCommission;
}
double commissionEmployee::getCommission()
{
return commissionRate;
}
void commissionEmployee::setGrossSales(double argSales)
{
grossSales = argSales;
}
double commissionEmployee::getGrossSales()
{
return grossSales;
}
double commissionEmployee::earnings()
{
return (commissionRate * grossSales);
}
void commissionEmployee::displayInformation()
{
employee::displayInformation();
cout <<"\ncommission rate: " << getCommission()
<<"\nweekly sales: " <<getGrossSales();
}
class basePlusCommissionEmployee : public commissionEmployee
{
private:
double salary;
public:
void setSalary(double);
double getSalary();
virtual double earnings();
virtual void displayInformation();
};
void basePlusCommissionEmployee::setSalary(double argSalary)
{
salary = argSalary;
}
double basePlusCommissionEmployee::getSalary()
{
return salary;
}
double basePlusCommissionEmployee::earnings()
{
return (getSalary() + commissionEmployee::earnings());
}
void basePlusCommissionEmployee::displayInformation()
{
employee::displayInformation();
commissionEmployee::displayInformation();
cout <<"salay: " <<salary;
cout <<endl;
}
int main()
{
int choice;
double salary;
string name, SSN;
cout <<"choose\n1)salaried employee\n2)commission employee\n3)base plus salaried
employee\nenter: ";
cin >> choice;
cout <<"enter name: ";
cin >> name;
cout <<"enter SSN: ";
cin >>SSN;
if(choice == 1)
{
employee *pointerObj = new salariedEmployee;
salariedEmployee obj;
obj.setName(name);
obj.setSSN(SSN);
cout <<"enter weekly salary: ";
cin >> salary;
obj.setSalary(salary);
system("cls");
cout <<"total earning of this employee: " <<pointerObj->earnings();
cout <<endl;
pointerObj->displayInformation();
}
}

You have two distinct and different objects...
First you have the object pointed to by pointerObj, and the only thing you do with that object is to call its displayInformation function.
Then you have the obj object, which is where you set all values.
If you want to print all the data you set for obj then you need to call displayInformation on obj instead:
obj.displayInformation();
Otherwise you should set all the information on the object pointed to be pointerObj and don't have the variable obj at all.
Or a possible third solution:
employee *pointerObj = &obj;

Related

How to declare a default constructor for subclass?

Very recently, I have started learning C++ full-time.
It is my understanding that constructors in C++ are not inherited by subclasses, and therefore must be declared in the subclass.
Below, I have a program that has a base class Car with a default constructor using default values for the 3 variables, then I have a subclass SportsCar that supposedly invokes the default constructor from the base class.
My problem is that I am having trouble figuring out a way to initialize the new variable acceleration for the subclass constructor to a value such as -2.
Here is my .h file
#include <iostream>
#include <string>
using namespace std;
#ifndef CAR_H_
#define CAR_H_
class Car {
public:
Car();
void SetName(string carName);
void SetMPH(int carMPH);
void SetPrice(double carPrice);
string GetName() const;
int GetMPH() const;
double GetPrice() const;
virtual void display() {
cout << "Car Information: " << endl;
cout << "Model Name: " << name << endl;
cout << "Top Speed: " << mph << " miles per hour" << endl;
cout << "Sales Price: $" << price << endl;
}
void SetInfo(string theName, int theMPH, double thePrice) {
name = theName;
mph = theMPH;
price = thePrice;
}
virtual ~Car() {
cout << "deletion complete" << endl;
}
private:
string name;
int mph;
double price;
};
Car::Car() {
name = "NoName";
mph = -1;
price = 0.0;
}
void Car::SetName(string carName) {
name = carName;
}
void Car::SetMPH(int carMPH) {
mph = carMPH;
}
void Car::SetPrice(double carPrice) {
price = carPrice;
}
string Car::GetName() const {
return name;
}
int Car::GetMPH() const {
return mph;
}
double Car::GetPrice() const {
return price;
}
class SportsCar : public Car {
public:
void SetAcceleration(double carAcceleration) {
acceleration = carAcceleration;
}
double GetAcceleration() const {
return acceleration;
}
void display() override {
Car::display();
cout << "0-60mph Acceleration: " << acceleration << endl;
}
private:
double acceleration;
};
#endif /* CAR_H_ */
Here is my .cpp file:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include "Car.h"
int main() {
Car* nullCar;
Car* regularCar1;
Car* regularCar2;
SportsCar* nullSportsCar;
vector<Car*> carsList;
unsigned int i;
nullCar = new Car();
carsList.push_back(nullCar);
regularCar1 = new Car();
regularCar1->SetName("2022 Honda Civic");
regularCar1->SetMPH(140);
regularCar1->SetPrice(22550.79);
carsList.push_back(regularCar1);
regularCar2 = new Car();
regularCar2->SetInfo("2022 Nissan Altima", 130, 24900.49);
carsList.push_back(regularCar2);
nullSportsCar = new SportsCar();
carsList.push_back(nullSportsCar);
for (i = 0; i < carsList.size(); i++) {
carsList.at(i)->display();
cout << endl;
}
return 0;
}
Here is the output:
Car Information:
Model Name: NoName
Top Speed: -1 miles per hour
Sales Price: $0
Car Information:
Model Name: 2022 Honda Civic
Top Speed: 140 miles per hour
Sales Price: $22550.8
Car Information:
Model Name: 2022 Nissan Altima
Top Speed: 130 miles per hour
Sales Price: $24900.5
Car Information:
Model Name: NoName
Top Speed: -1 miles per hour
Sales Price: $0
0-60mph Acceleration: 0
It works fine, but I want the last output "0-60mph Acceleration" to read -2 instead of 0. I just don't know how to declare a default constructor for the subclass to do that.
Do you mean:
class SportsCar : public Car {
public:
SportsCar()
: Car() // Parent Init
// Preferrer using initializer list for members
// After Parents come members
, acceleration(-2)
{}
....
};

How to call a function of inner class in outer class?

class student
{
private:
int admno;
char sname[20];
class Student_Marks
{
private:
float eng, math, science, computer, Hindi;
float total;
public:
void sMARKS()
{
cin >> eng >> math >> science >> computer >> Hindi;
}
float cTotal()
{
total = eng + math + science + computer + Hindi;
return total;
}
};
public:
void showData()
{
cout << "\n\nAdmission Number :" << admno;
cout << "\nStudent Name :" << sname;
cout << "\nTotal Marks :" << cTotal();
}
};
I want to call inner class function cTotal() , in outer class function showData().
I am getting error in accessing inner class function in outer class.
Your Student_Marks is just a class definition. Without having an object of the Student_Marks class in student, you can not call its member (e.g. cTotal()).
You can have a look at the sample code below:
class student
{
private:
int admno;
// better std::string here: what would you do if the name exceeds 20 char?
char sname[20];
class Student_Marks {
// ... code
};
Student_Marks student; // create a Student_Marks object in student
public:
// ...other code!
void setStudent()
{
student.sMARKS(); // to set the `Student_Marks`S members!
}
void showData() /* const */
{
// ... code
std::cout << "Total Marks :" << student.cTotal(); // now you can call the cTotal()
}
};
Also have a read: Why is "using namespace std;" considered bad practice?
As soon as you call it "nested class" instead of inner class, you might be able to find appropriate references in language guides. It's only a definition of type within enclosing class's scope, you have to create an instance of such class to work with. E.g.
class student
{
private:
int admno;
char sname[20];
class Student_Marks
{
private:
float eng,math,science,computer,Hindi;
float total;
public:
void sMARKS()
{
cout<<"Please enter marks of english,maths,science,computer,science and hindi\n ";
cin>>eng>>math>>science>>computer>>Hindi;
}
float cTotal()
{
total=eng+math+science+computer+Hindi;
return total;
}
};
Student_Marks m_marks; // marks of this student
Another problem with your code that your approach to input of input is horribly lacking of error-checking...

Diamond problem with Multiple inheritance C++

I have a homework task with a given main.cpp code which is not allowed to be changed. According to that main.cpp and simple input and output(which is down below) example I must to finish the program.
My tries are: I'm trying to create 4 classes, class Person; class Worker; class Student; class InService; in my main function through instantiating an object of InService class I pass 4 parameters (name, sex, studentNo, workerNo); and with help of pointer of type of Base class, have the desired output. The error it shows is:
[Error] no unique final overrider for 'virtual std::string Person::getName()' in 'InService'
[Error] no unique final overrider for 'virtual int Person::getSex()' in 'InService'
I've tried to use virtual inheritance for that, but I can't really figure out how to solve this problem. I did some research on virtual inheritance, and referenced to other experts answers, but still getting confused with whole OOP stuff.
//Inservice.h
#include<string>
using namespace std;
class Person{
public:
Person();
~Person();
string name;
int sex;
virtual string getName() = 0;
virtual int getSex() = 0;
};
///////////////////////////////////////////////////
class Student:virtual public Person{
public:
Student();
~Student();
string sno;
virtual string getName() {
return name;
}
virtual int getSex(){
return sex;
}
string getSno(){
return sno;
}
};
//////////////////////////////////////////////////
class Worker:virtual public Person{
public:
Worker();
~Worker();
string wno;
virtual std::string getName(){
return name;
}
virtual int getSex(){
return sex;
}
string getWno(){
return wno;
}
};
///////////////////////////////////////////////////////
class InService: public Student, public Worker{
public:
InService(string _name, int _sex, string _sno, string _wno){
Person::name = _name;
Person::sex - _sex;
Worker::wno = _wno;
Student::sno = _sno;
}
};
///////////////////////////////////////////////////////
//main.cpp
#include <iostream>
#include "inservice.h"
using namespace std;
int main() {
string name, sno, wno;
int sex;
cin >> name;
cin >> sex;
cin >> sno;
cin >> wno;
InService is(name, sex, sno, wno);
Person* p = &is;
Student* s = &is;
Worker* w = &is;
cout << p->getName() << endl;
cout << p->getSex() << endl;
cout << s->getName() << endl;
cout << s->getSex() << endl;
cout << s->getSno() << endl;
cout << w->getName() << endl;
cout << w->getSex() << endl;
cout << w->getWno() << endl;
return 0;
}
Suppose my input is:
Jack
1 //1-for male; 0 -for female
12345678 //studentNo
87654321 //workerNo
I expect the output to be:
Jack
1
12345678
Jack
1
87654321
InService(string _name, int _sex, string _sno, string _wno){
Person::name = _name;
Person::sex - _sex;
Worker::wno = _wno;
Student::sno = _sno;
}
There's a typo there, Person::sex - _sex; should be Person::sex = _sex;
Also you can remove name and sex virtual function and have it just a standard function in Person, since it's exactly the same for all classes that derive from it. That will remove the ambiguity of which getName and getSex function that InService class virtual table needs to point to.

Derived Class C++ [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 6 years ago.
I know that it can be a stupid but I even don't know how to name this question. I'm non native English. I learn C++ from a book and there is a program which shows name and pay rate of employee (base class) and Manager (derived class) with added bool variable salaried. Here is the source code:
//base class
class Employee {
private:
string name;
double pay;
public:
Employee() {
name = "";
pay = 0;
}
Employee(string empName, double payRate) {
name = empName;
pay = payRate;
}
string getName() const {
return name;
}
void setName(string empName) {
name = empName;
}
double getPay() const {
return pay;
}
void setPay(double payRate) {
pay = payRate;
}
string toString() {
stringstream stm;
stm << name << ": " << pay;
return stm.str();
}
};
//derived class
class Manager : public Employee {
private:
bool salaried;
public:
Manager(string name, double payRate, bool isSalaried)
:Employee(name, payRate)
{
salaried = isSalaried;
}
bool getSalaried() {
return salaried;
}
};
int main()
{
Employee emp1("Mary Smith", 15.00);
cout << "Employee name: " << emp1.getName() << endl;
cout << "Employee pay rate: " << emp1.getPay() << endl;
Manager emp2("Bob Brown", 1500, true);
cout << "Employee name: " << emp2.getName() << endl;
cout << "Employee pay rate: " << emp2.getPay() << endl;
cout << "Is Salaried: " << emp2.getSalaried() << endl;
return 0;
}
Can someone explain me why this part
:Employee(name, payRate)
must be added to code to work properly?
The part
:Employee(name, payRate)
you mention is used to call the constructor
Employee(string empName, double payRate)
of the base class Employee before executing the body of the constructor
Manager(string name, double payRate, bool isSalaried)
of the derived class Manager.
It calls the base class's (Employee) constructor and passes the name and payRate to it because they are members of Employee.
:Employee(name, payRate)
is the initialisation of the base class that class Manager inherits.
In fact without this line the code should compile fine(because you have a default constructor for Employee), but the fields inherited from Employee will not get properly initialized in emp2. What this portion of the code does is to call the constructor of Employee to initialize the fields inherited from that class.
What come after the colon on the constructor called initialization list and in your case it just initiate the base class with the suitable constructor
The code can work properly even without the constructor(i.e..you can use the default constructor to accept the variables and implement two methods for filling the name and pay.)
class Employee {
private:
string name;
string temp_name;
double temp_pay;
double pay;
public:
Employee() {
name = temp_name;
pay = temp_pay;
}
void getTempname(string tem){temp_name = tem;}
void getTemppay(double py){ temp_pay = pay;}
};

Is it possible to call a method from main if it is private? If not, how would it be possible?

I am trying to get this program to start running but currently I just get errors. I am not sure how to get this to work. If I change the class SavingsAccount to public it should be okay, but I am required to keep it as is.
The problem is in the main function.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class SavingsAccount
{
int accountType;
string ownerName;
long ssn;
double accountClosurePenaltyPercent, accountBalance;
void Information();
inline double AccountClosureLoss()
{
return (accountBalance * accountClosurePenaltyPercent);
}
void OutputInformation();
};
void SavingsAccount::Information()
{
cout << "Enter Account Type (1 for Checking or 2 for Savings): ";
cin >> accountType;
cout << "Enter owner name: ";
getline(cin, ownerName);
cout << "Enter the Social Security Number: ";
cin >> ssn;
cout << "Enter the percent penalty for closing account(decimal form): ";
cin >> accountClosurePenaltyPercent;
cout << "Enter the account balance: ";
cin >> accountBalance;
}
void SavingsAccount::OutputInformation()
{
cout << "Account Type: " << endl;
cout << "Name: " << ownerName << endl;
cout << "SSN: " << ssn << endl;
cout << "Account Closure Penaly %: " << accountClosurePenaltyPercent << endl;
cout << "Account Balance: " << accountBalance;
}
int main(void)
{
SavingsAccount.Information();
SavingsAccount.AccountClosureLoss();
SavingsAccount.OutputInformation();
return 0;
}
What I tried so far.
int main(void)
{
SavingsAccount John;
John.Information();
John.AccountClosureLoss();
John.OutputInformation();
return 0;
}
Any suggestions?
Well by default member functions are private, so you can always add them into public as follows:
class SavingsAccount
{
private:
int accountType;
string ownerName;
long ssn;
public:
double accountClosurePenaltyPercent, accountBalance;
void Information();
inline double AccountClosureLoss()
{
return (accountBalance * accountClosurePenaltyPercent);
}
void OutputInformation();
};
You will now be able to call them from the main.
Since you cannot change the SavingsAccount class, and since it prohibits access to it's members (private is the default), you are not supposed to use any menber of that class.
"The problem is in the main function": no, it is in the design of your class. A class with nothing public is not useful.
There is no clean solution to your problem.
A solution on the borderline of changing the class would be in defining an 'interface', and making the (unchanged) class inherit that interface:
class Account {
public:
virtual ~Account(){}
virtual void Information() = 0;
virtual double AccountClosureLoss() = 0;
virtual void OutputInformation() = 0;
};
class SavingsAccout : public Account {
... body remains unchanged
};
The main will use Account iso SavingsAccount:
SavingsAccount savingsAccount;
Account& account = savingsAccount;
// should be accessible via the `Account` interface.
account.AccountClosureLoss();
You're trying to use member attributes inside your methods, yet you're trying to use your methods without an instance. All the member attributes' values are stored inside your instances, so you need an instance first. Add it into your main function:
int main(void)
{
SavingsAccount myAccount;
myAccount.Information();
myAccount.AccountClosureLoss();
myAccount.OutputInformation();
return 0;
}
Also your methods are defined to be private, you should always use public: and private: as following:
class SavingsAccount
{
public:
void Information();
inline double AccountClosureLoss()
{
return (accountBalance * accountClosurePenaltyPercent);
}
void OutputInformation();
private:
int accountType;
string ownerName;
long ssn;
double accountClosurePenaltyPercent;
double accountBalance;
};
You can't use methods without an instance. Even if you could (static maybe?) you can't use any member attributes inside them, so it'd be useless to include it into the class.
You must declare an instance of the SavingsAccount class first. For example:
int main()
{
SavingsAccount account;
account.Information();
...
return 0;
}
Additionally, yes, the methods of the class that you want to call must be public.