The C++ method is not getting overridden? - c++

class People {
public:
People(string name);
void setName(string name);
string getName();
void setAge(int age);
int getAge();
virtual void do_work(int x);
void setScore(double score);
double getScore();
protected:
string name;
int age;
double score;
};
class Student: public People {
public:
Student(string name);
virtual void do_work(int x);
};
class Instructor: public People {
public:
Instructor(string name);
virtual void do_work(int x);
};
People::People(string name) {
this->name = name;
this->age = rand()%100;
}
void People::setName(string name) {
this->name = name;
}
string People::getName() {
return this->name;
}
void People::setAge(int age) {
this->age = age;
}
int People::getAge() {
return this->age;
}
void People::setScore(double score) {
this->score = score;
}
double People::getScore() {
return this->score;
}
void People::do_work(int x) {
}
Student::Student(string name):People(name){
this->score = 4 * ( (double)rand() / (double)RAND_MAX );
}
void Student::do_work(int x) {
srand(x);
int hours = rand()%13;
cout << getName() << " did " << hours << " hours of homework" << endl;
}
Instructor::Instructor(string name): People(name) {
this->score = 5 * ( (double)rand() / (double)RAND_MAX );
}
void Instructor::do_work(int x) {
srand(x);
int hours = rand()%13;
cout << "Instructor " << getName() << " graded papers for " << hours << " hours " << endl;
}
int main() {
Student student1("Don");
Instructor instructor1("Mike");
People t(student1);
t.do_work(2);
}
Why the do_work class is not getting overridden ? There is a people class and the Instructor and Student class are inheriting those classes. There is a virtual method in People class, which is implemented in Student and Instructor. But it is not getting overridden ? Thanks in advance !

You need to have pointers or references to objects to make overriding work:
Student* student1 = new Student("Don");
Instructor* instructor1 = new Instructor("Mike");
People* t = student1;
t->do_work(2);
And please don't forget to delete your allocated memory:
delete student1;
delete instructor1;
That would be just enough to make it work, but for the sake of safety and avoiding memory leaks, you can just go:
#include <memory>
...
int main() {
auto student1 = std::make_unique<Student>("Don");
auto instructor1 = std::make_unique<Instructor>("Mike");
People* t = student1.get();
t->do_work(2);
}
Also please consider declaring a virtual destructor in your base class, that would be a must if you inherit from People and add a member field in the inherited class:
class People {
public:
...
virtual ~People() {}
protected:
...
}

Related

C++ Can not manage to display the class datatype array

This is the code I wrote, total beginner
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
public:
string ID;
string name;
string surname;
string department;
string email;
public:
//get and set functions for ID, Name, Surname, Department, Email properties
string getID()
{
return this->ID;
};
void setID(string _ID)
{
this->ID = _ID;
};
string getName()
{
return this->name;
};
void setName(string _name)
{
this->name = _name;
};
string getSurname()
{
return this->surname;
};
void setSurname(string _surname)
{
this->surname = _surname;
};
string getDepartment()
{
return this->department;
};
void setDepartment(string _department)
{
this->department = _department;
};
string getEmail()
{
return this->email;
};
void setEmail(string _email)
{
this->email = _email;
};
};
//inherit Student class from Person class
class Student :public Person
{
private:
int student_counter = 0;
public:
//constructor
Student()
{
};
Student(string id, string Name, string Surname, string Department, string Email)
{
setID(id);
setName(Name);
setSurname(Surname);
setDepartment(Department);
setEmail(Email);
}
//student add
void addStudent(string id, string Name, string Surname, string Department, string Email)
{
if (student_counter >= 100)
{
cout << "cant add more students";
}
else
{
Student _S[100]
Student newS;
newS.setID(id);
newS.setName(Name);
newS.setSurname(Surname);
newS.setDepartment(Department);
newS.setEmail(Email);
_S[student_counter] = newS;
student_counter++;
}
}
//display students
void display()
{
for (int i = 0; i < student_counter; i++)
{
cout << _S[i].getID() << " - ";
}
}
};
};
int
main()
{
Student stu;
stu.addStudent("ST123456", "Ege", "Inan", "CS", "ege # gmail.com");
stu.display();
}
The problem is here
//inherit Student class from Person class
class Student :public Person
{
private:
int student_counter = 0;
public:
//constructor
Student()
{
};
Student(string id, string Name, string Surname, string Department, string Email)
{
setID(id);
setName(Name);
setSurname(Surname);
setDepartment(Department);
setEmail(Email);
}
//student add
void addStudent(string id, string Name, string Surname, string Department, string Email)
{
if (student_counter >= 100)
{
cout << "cant add more students";
}
else
{
Student _S[100];
Student newS;
newS.setID(id);
newS.setName(Name);
newS.setSurname(Surname);
newS.setDepartment(Department);
newS.setEmail(Email);
_S[student_counter] = newS;
student_counter++;
}
}
//display students
void display()
{
for (int i = 0; i < student_counter; i++)
{
cout << _S[i].getID() << " - ";
}
}
};
};
The error message I get is this:
main.cpp:106:9: error: ‘_S’ was not declared in this scope
106 | cout<<_S[i].getID()<<" - ";
| ^~
I tried moving the definition of Student _S to the private part of student class like this:
class Student :public Person
{
private:
int student_counter = 0;
Student _S[100];
public:
//constructor
Student()
{
};
Student(string id, string Name, string Surname, string Department, string Email)
{
setID(id);
setName(Name);
setSurname(Surname);
setDepartment(Department);
setEmail(Email);
}
//student add
void addStudent(string id, string Name, string Surname, string Department, string Email)
{
if (student_counter >= 100)
{
cout << "cant add more students";
}
else
{
Student newS;
newS.setID(id);
newS.setName(Name);
newS.setSurname(Surname);
newS.setDepartment(Department);
newS.setEmail(Email);
_S[student_counter] = newS;
student_counter++;
}
}
//display students
void display()
{
for (int i = 0; i < student_counter; i++)
{
cout << _S[i].getID() << " - ";
}
}
};
};
But then I got this:
65 | Student _S[100];
| ^~
main.cpp:61:7: note: definition of ‘class Student’ is not complete until the closing brace
61 | class Student:public Person
| ^~~~~~~
What would be the best way of handling this? where to define the array to get the program to run as intended?
In the first code, _S is a local variable inside of addStudent(), so display() can't access it.
Your second code is better, in that display() can now access _S. But a Student object can't hold any data members that are also Student objects, you would end up with an endless recursive allocation.
To accomplish what you want, you need to make _S, student_counter, addStudent(), and display() be static members of the Student class, eg:
class Student :public Person
{
private:
static int student_counter;
static Student _S[100];
public:
//constructor
Student()
{
};
Student(string id, string Name, string Surname, string Department, string Email)
{
setID(id);
setName(Name);
setSurname(Surname);
setDepartment(Department);
setEmail(Email);
}
//student add
static void addStudent(string id, string Name, string Surname, string Department, string Email)
{
if (student_counter >= 100)
{
cout << "cant add more students";
}
else
{
Student newS;
newS.setID(id);
newS.setName(Name);
newS.setSurname(Surname);
newS.setDepartment(Department);
newS.setEmail(Email);
_S[student_counter] = newS;
student_counter++;
}
}
//display students
static void display()
{
for (int i = 0; i < student_counter; i++)
{
cout << _S[i].getID() << " - ";
}
}
};
int Student::student_counter = 0;
Student Student::_S[100];
int main()
{
Student::addStudent("ST123456", "Ege", "Inan", "CS", "ege # gmail.com");
Student::display();
}
Online Demo

Passing a class object into a templated classes private member scope

Hi I'm new to c++ and trying to learn something. maybe it can't be done. but I want to:
create an Employee class that records all employees, and their information (see my code below).
Then I want to make a templated class for a linked list. inside the private scope of this class, I will have a "T data" type. I want my constructor to instantiate an "Employee" every time a LinkedList object is created in the main. I hope that makes sense. I have my code working the way I set it up now. However, I'm not necessarily templating it the way I want.
template <class T>
class Employees { //Parent
private:
int EmployeeID;
double Paycheck;
int Hours;
double Payrate;
std::string Employeename;
public:
Employees(int ID, double Prate, std::string EName) {
EmployeeID = ID;
Payrate = Prate;
Employeename = EName;
Hours = 0; //our constructor can just give each Employee 0 hours.
Paycheck = 0.00;
}
Employees() {
EmployeeID = 0;
Payrate = 0.0;
Employeename = "N/A";
Hours = 0;
Paycheck = 0.00;
}
void setPaycheck() {
std::cout << std::fixed;
std::cout << std::setprecision(2);
double i = Payrate;
i = i * 100;
i = i * Hours;
i = i / 100;
Paycheck = i;
//so I'm not sure why I couldn't just cast the double, but the complier kept rounding down each time.
// I had to make a conversion of my decimal into a whole number and then go back and divide it to get the
// paycheck amount.
};
void setEMPname(std::string Name) {
Employeename = Name;
}
void setPayrate(double payrate) {
Payrate = payrate;
}
void setEMPid(int IDnum) {
EmployeeID = IDnum;
}
void setHOURS(int hours) {
Hours += hours;
}
int IDReturn() { return EmployeeID; }
int HoursReturn() { return Hours; }
double PaycheckReturn() { return Paycheck; }
double PayrateReturn() { return Payrate; }
std::string NameReturn() { return Employeename; }
};
template <class T>
class LinkedLists :Employees<T> { //child
friend class Employees<T>;
private:
////I want change the object below to "T data"
Employees<T> EmployeeObject; //contains all the employee information
LinkedLists<T>* nextlink;
LinkedLists<T>* prevlink;
public:
LinkedLists() {
EmployeeObject;
nextlink = nullptr;
prevlink = nullptr;
}
void setname(std::string Name) {
EmployeeObject.setEMPname(Name);
}
void setPrate(double payrate) {
EmployeeObject.setPayrate(payrate);
}
void setid(int IDnum) {
EmployeeObject.setEMPid(IDnum);
}
void setPayCheck() { EmployeeObject.setPaycheck(); }
LinkedLists<T>*& setLinkforward() {
return nextlink;
}
LinkedLists<T>*& setLinkbackward() {
return prevlink;
}
int idReturn() { return EmployeeObject.IDReturn(); }
double payrateReturn() { return EmployeeObject.PayrateReturn(); }
std::string nameReturn() { return EmployeeObject.NameReturn(); }
void AddHours(int Hours) { EmployeeObject.setHOURS(Hours); }
int ReturnHours() { return EmployeeObject.HoursReturn(); }
double ReturnPayCheck() {
return EmployeeObject.PaycheckReturn();
}
};

Cannot call getter method unless specifying "this" keyword

Why does the example from a tutorial page works without having the this keyword in the constructor?
The code from the website:
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle ();
Rectangle (int,int);
int getWidth() {
return width;
}
};
Rectangle::Rectangle () {
width = 5;
height = 5;
}
Rectangle::Rectangle (int a, int b) {
width = a;
height = b;
}
int main () {
Rectangle rect (3,4);
Rectangle rectb;
cout << "rect area: " << rect.getWidth() << endl;
cout << "rectb area: " << rectb.getWidth() << endl;
return 0;
}
My code:
class Person {
int age;
std::string name;
public:
Person();
Person(int, std::string);
std::string * getName() {
return &name;
}
int * getAge() {
return &age;
}
};
Person::Person () {
age = 25;
name = "John";
}
Person::Person (int age, std::string name){
// This is the part :
this->age = age;
this->name = name;
}
int main() {
Person john(45, "Doe");
printf("Name %d \n", *john.getAge() );
std::cout << "Age " << *john.getName() << std::endl;
return 0;
}
As you can see in my code i must use this->name, if I don't then the values are not assigned.
On the other hand, the example code from the website works with or without this->
Why does this happen?
The problem is that the parameters of the function have the same name as the class so the compiler doesn't know which one you are talking about unless you use this. You can solve this by changing the names of the variables or you could use a member initialization list
Person::Person (int age, std::string name) : name(name), age(age) {}
As a note I like to use the same name as the class variable but add a _ after the name to make it different. So in this case I would have done:
Person::Person (int age_, std::string name_) : name(name_), age(age_) {}
This makes it easier to differentiate between the class members and the constructor parameters.
Person::Person (int age, std::string name){
// This is the part :
this->age = age;
this->name = name;
}
Because your private variable is called name, and the variable you send in is also called name, you use this-> to specify which variable called name you are using.

Getting values from a vector of object pointers

I need to write the name, act# balance and address of the object that is stored in the vector, to a file.
I believe I have the program to push the objects into the vectors, but since they are vectors of object pointers I am having problems figure out how to call the object and print all 3 objects out.
Main.cpp
vector<Account*> accounts;
accounts.push_back(new Savings(new Person("Bilbo Baggins", "43 Bag End"), 1, 500, 0.075));
accounts.push_back(new Checking(new Person("Wizard Gandalf", "Crystal Palace"), 2, 1000.00, 2.00));
accounts.push_back(new Savings(new Person("Elf Elrond", "Rivendell"), 3, 1200, 0.050));
ofstream outFile;
outFile.open("accounts.txt");
if (outFile.fail())
{
cout << "\nYour file did not open, the program will now close!\n";
system("PAUSE");
return 0;
}
else
{
cout << "\nBINGO!!! It worked.\n\n";
system("PAUSE");
cout << "\n";
}
// New : Using a loop, send messages to each of the three Account objects to write themselves out to the file.
cout << "\nNow we are going to write the information to \"Accounts.txt\" \n\n";
system("PAUSE");
for (int i = 0; i < accounts.size(); i++) {
accounts[i]->writeAccount(outFile);
}
Account.h
#pragma once
#include <string>
#include <iostream>
#include "Person.h"
using namespace std;
// Account class - abstract/parent class
class Account
{
private:
int actNumber;
double actBallance;
Person PersonName;
public:
Account();
Account(int, double, Person*);
int getActNumber();
virtual double getActBallance();
string getName();
string getAdd();
void deposit(double);
void withdrawl(double);
virtual void writeAccount(ofstream&);
virtual void readAccount(ifstream&);
void testAccount(int i);
};
// Checking class: inherits from the Account class
class Checking : public Account
{
private:
double monthlyFee;
public:
Checking();
Checking(Person*, int, double, double);
void setMonthlyFee(double);
double getActBallance();
void writeAccount(ofstream&);
void readAccount(ifstream&);
};
// Savings class: inherits from the Account class
class Savings : public Account
{
private:
int interestRate;
public:
Savings();
Savings(Person*, int, double, double); // person, act#, Ballance, Interest Rate
void setInterestRate(double);
double getActBallance();
void writeAccount(ofstream&);
void readAccount(ifstream&);
};
Account.cpp
#include "Account.h"
#include <string>
using namespace std;
Account::Account()
{
actNumber = 0;
actBallance = 0.0;
}
Account::Account(int act, double bal, Person* name)
{
actNumber = act;
actBallance = bal;
}
int Account::getActNumber()
{
return actNumber;
}
double Account::getActBallance()
{
return actBallance;
}
string Account::getName()
{
return PersonName.getName();
}
string Account::getAdd()
{
return PersonName.getAddress();
}
void Account::deposit(double money)
{
actBallance += money;
}
void Account::withdrawl(double money)
{
actBallance -= money;
}
void Account::writeAccount(ofstream& output)
{
output << actNumber << "\n" << actBallance << "\n" << PersonName.getName() << "\n" << PersonName.getAddress() << endl;
}
void Account::readAccount(ifstream& output)
{
output >> actNumber;
output >> actBallance;
}
// Checking Account
Checking::Checking() {
monthlyFee = 0;
}
Checking::Checking(Person* per, int actNum, double bal, double interest) {
bal -= monthlyFee;
Account:Account(actNum, bal, per);
}
void Checking::setMonthlyFee(double fee) {
monthlyFee = fee;
}
double Checking::getActBallance() {
double ballance = Account::getActBallance();
return ballance = monthlyFee;
}
void Checking::readAccount(ifstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance() - monthlyFee;
output >> actNumber;
output >> actBallance;
}
void Checking::writeAccount(ofstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance();
output << actNumber << "\n" << actBallance << endl;
}
// Savings Account
Savings::Savings() {
interestRate = 0;
}
// Savings(Person, int, double, double) // person, act#, Ballance, Interest Rate
Savings::Savings(Person* per, int actNum, double bal, double interest) {
bal += (bal * interest);
Account:Account(actNum, bal, per);
}
void Savings::setInterestRate(double rate) {
interestRate = rate;
}
double Savings::getActBallance() {
double ballance = Account::getActBallance();
return ballance + (ballance * interestRate);
}
void Savings::readAccount(ifstream& output) {
double actBallance = Account::getActBallance();
int actNumber = Account::getActNumber();
actBallance += (actBallance * interestRate);
output >> actNumber;
output >> actBallance;
}
void Savings::writeAccount(ofstream& output) {
int actNumber = Account::getActNumber();
int actBallance = Account::getActBallance();
output << actNumber << "\n" << actBallance << endl;
}
I realize I am so far off... but I have been at this for HOURS and I can not figure out for the life of me, but to take the vector of object pointers and output the objects values.
Person.h
#pragma once
#include <string>
#include <fstream>
using namespace std;
class Person
{
private:
string name;
string address;
public:
Person();
Person(string a, string b);
string getName();
string getAddress();
void writePerson(ofstream&);
void readPerson(ifstream&);
};
Person.cpp
#include "Person.h"
#include <string>
using namespace std;
Person::Person()
{
name = "NAME";
address = "123 STREET";
}
Person::Person(string a, string b)
{
name = a;
address = b;
}
string Person::getName()
{
return name;
}
string Person::getAddress()
{
return address;
}
void Person::writePerson(ofstream& output)
{
output << name << " " << address << endl;
}
void Person::readPerson(ifstream& output)
{
output >> name;
output >> address;
Person(name, address);
}
Read again your course books on constructors: there are severe issues in all of your constructors. As a result, you don't initialize the object member variables, and you effectively end up printing lots of zeros and empty strings...
Firstly, for your base-class, you must initialize the person name. You should have written:
Account::Account(int act, double bal, Person* name)
: actNumber(act)
, actBallance(bal)
, PersonName(name)
{}
Secondly, for your derived classes, the initialisation of the base-class must be done in the initializer-list, not in the body of the ctor. Here is for exemple the correct definition for the Checking's ctor:
Checking::Checking(Person* per, int actNum, double bal, double interest)
: Account(actNum, bal, per)
, monthlyFee(-bal)
{}
Thirdly, be careful to initialize the member variables with the arguments of the ctor. You sometimes do the opposite and assign the ctor arguments with the (uninitialized) member variables.
BTW, Account is a base-class for a polymorphic hierarchy: thus, the Account destructor must be declared virtual.

Adding two different Objects by overloading operator+ C++

I've been trying to figure out how to add a private member from Object A, to a private member from Object B.
Both Cat and Dog Class's inheriate from the base class Animal. I have a thrid class 'MyClass', that I want to inheriate the private members of the Cat and Dog class. So in MyClass, I have a friend function to overload the + operator. THe friend function is defined as follows:
MyClass operator+(const Dog &dObj, const Cat &cObj);
I want to access dObj.age and cObj.age within the above function, invoke by this statement in main:
mObj = dObj + cObj;
Here is the entire source for a complete reference into the class objects:
#include <iostream>
#include <vld.h>
using namespace std;
class Animal
{
public :
Animal() {};
virtual void eat() = 0 {};
virtual void walk() = 0 {};
};
class Dog : public Animal
{
public :
Dog(const char * name, const char * gender, int age);
Dog() : name(NULL), gender(NULL), age(0) {};
virtual ~Dog();
void eat();
void bark();
void walk();
private :
char * name;
char * gender;
int age;
};
class Cat : public Animal
{
public :
Cat(const char * name, const char * gender, int age);
Cat() : name(NULL), gender(NULL), age(0) {};
virtual ~Cat();
void eat();
void meow();
void walk();
private :
char * name;
char * gender;
int age;
};
class MyClass : private Cat, private Dog
{
public :
MyClass() : action(NULL) {};
void setInstance(Animal &newInstance);
void doSomething();
friend MyClass operator+(const Dog &dObj, const Cat &cObj);
private :
Animal * action;
};
Cat::Cat(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Cat::~Cat()
{
delete name;
delete gender;
age = 0;
}
void Cat::walk()
{
cout << name << " is walking now.. " << endl;
}
void Cat::eat()
{
cout << name << " is eating now.. " << endl;
}
void Cat::meow()
{
cout << name << " says meow.. " << endl;
}
Dog::Dog(const char * name, const char * gender, int age) :
name(new char[strlen(name)+1]), gender(new char[strlen(gender)+1]), age(age)
{
if (name)
{
size_t length = strlen(name) +1;
strcpy_s(this->name, length, name);
}
else name = NULL;
if (gender)
{
size_t length = strlen(gender) +1;
strcpy_s(this->gender, length, gender);
}
else gender = NULL;
if (age)
{
this->age = age;
}
}
Dog::~Dog()
{
delete name;
delete gender;
age = 0;
}
void Dog::eat()
{
cout << name << " is eating now.. " << endl;
}
void Dog::bark()
{
cout << name << " says woof.. " << endl;
}
void Dog::walk()
{
cout << name << " is walking now.." << endl;
}
void MyClass::setInstance(Animal &newInstance)
{
action = &newInstance;
}
void MyClass::doSomething()
{
action->walk();
action->eat();
}
MyClass operator+(const Dog &dObj, const Cat &cObj)
{
MyClass A;
//dObj.age;
//cObj.age;
return A;
}
int main()
{
MyClass mObj;
Dog dObj("B", "Male", 4);
Cat cObj("C", "Female", 5);
mObj.setInstance(dObj); // set the instance specific to the object.
mObj.doSomething(); // something happens based on which object is passed in
dObj.bark();
mObj.setInstance(cObj);
mObj.doSomething();
cObj.meow();
mObj = dObj + cObj;
return 0;
}
If you want to access a private member of Dog, then your operator has to be a friend of Dog, not just a friend of some derived class of Dog.
If you add friend MyClass operator+(const Dog &dObj, const Cat &cObj); to the definition of class Cat and class Dog, then the function will have access to dObj.age and cObj.age.
Alternatively, you could add friend MyClass; to the definitions of class Cat and class Dog, but then all of MyClass's functions have access to all of Cat and Dog's internals.
Alternatively alternatively, you could make age protected rather than private.