C++ Inheritance of functions, passing in arguments - c++

Base class : Employee
Derived class : Regular
Employee.cpp
void Employee::setValue(string id, string name, double s, int n)
{
empID = id;
empName = name;
salary = s;
}
Regular.cpp
void Regular::setValue(string id, string name, double s, int n)
{
annualLeave = n;
}
Employee::setValue() only stores the first 3 arguments passed in, but not int n, too.
I'm supposed to inherit that setValue() in Regular::setValue() and then just pass in the arguments, but this time store int n to annualLeave.
How do I do that?
Or, is there a way for me to set int n in the base class for the child class?

You can call the base class's implementation:
void Regular::setValue(string id, string name, double s, int n) {
annualLeave = n;
return Employee::setValue(std::move(id), std::move(name), s);
}
Otherwise, make base class polymorphic:
struct Employee {
void setValue(string id, string name, double s, int n) {
empID = std::move(id);
empName = std::move(name);
salary = s;
setLeave(n);
}
virtual ~Employee() {}
protected:
virtual void setLeave(int) = 0;
string empID;
string empName;
double salary;
};
struct Regular: Employee {
private:
void setLeave(int n) override { annualLeave = n; }
int annualLeave;
};

If necessary to keep a single-signature setValue function, it is possible to do it like that:
-
Includes:
#include <any>
#include <map>
#include <string>
-
Employee.h:
class CEmployee
{
protected:
virtual void setValue(std::map<std::string, std::any> &info);
int m_empID = 0;
std::string m_empName = {'\0'};
int m_salary = 0;
}
Employee.cpp:
void CEmployee::setValue(std::map<std::string, std::any> &info)
{
std::any item;
item = info["empID"];
if (item.has_value())
m_empID = std::any_cast<int>(item); // int
item = info["empName"];
if (item.has_value())
m_empName = std::any_cast<std::string>(item); // std::string
item = info["salary"];
if (item.has_value())
m_salary = std::any_cast<int>(item); // int
}
-
Regular.h:
class CRegular : public CEmployee
{
public:
void setValue(std::map<std::string, std::any> &info) override;
protected:
std::string m_annualLeave = {'\0'};
}
Regular.cpp:
void CRegular::setValue(std::map<std::string, std::any> &info)
{
std::any item;
CEmployee::setValue(info);
item = info["annualLeave"];
if (item.has_value())
m_annualLeave = std::any_cast<std::string>(item); // std::string
}
-
& call it like that:
void MyClass::HardcodedExample()
{
CRegular regular_employee;
std::map<std::string, std::any> info, update;
info["empID"] = { 100 };
info["empName"] = { std::string("Trump") };
info["salary"] = { 1000000 };
info["annualLeave"] = { std::string("29 Jul 2018") };
regular_employee.setValue(info); // Set all info
// Or:
update["annualLeave"] = { std::string("29 Dec 2018") };
regular_employee.setValue(update); // Update just "annualLeave"
// Or:
update["salary"] = { 1200000 };
update["annualLeave"] = { std::string("04 Jul 2018") };
regular_employee.setValue(update); // Update "salary" & "annualLeave"
}
-
Otherwise, setValue with 3 parameters to base-class, & with 4 parameters to the derived-class (that calls to the base-class with the 3 parameters and sets by itself the 4th one) - similar to what #RemyLebeauis offers - is a better solution.
-
& better to use #define / enum keys instead of string-keys (& change the key-type of the map accordingly), but this is a different issue.

Related

Easiest way for a child object to inherit all of parent object's data in C++?

I wanted to see if there is a way to set a child class object to inherit all the data from a parent class.
ex.
InventoryBook allBooks[20];
SoldBook child[0] = allBooks[0];
For context, I'm trying to write a program in C++ that keeps track of a hypothetical book store's inventory and I wanted to create a class that handles a sale transactions.
class BookData
{
protected:
char bookTitle[51] = {},
isbn[14] = {},
author[31] = {},
publisher[31] = {},
dateAdded[11] = {};
public:
void setTitle(char newTitle[]);
void setISBN(char newISBN[]);
void setAuthor(char newAuthor[]);
void setPub(char newPub[]);
char *getTitle();
char *getISBN();
char *getAuthor();
char *getPub();
char *getDateAdded();
bool bookMatch(char[]);
};
class InventoryBook : public BookData
{
protected:
int qtyOnHand;
double wholesale,
retail;
public:
void setDateAdded(char newDate[]);
void setQty(int newQty);
void setWholesale(double newWhole);
void setRetail(double newRetail);
int isEmpty();
void removeBook();
void delBook();
int getQty();
double getWholesale();
double getRetail();
};
class SoldBook : public InventoryBook
{
private:
const double taxRate = 0.06;
int qtySold;
double tax = 0, subtotal = 0;
static double total;
public:
SoldBook calcTax()
{
this->tax = qtySold * retail * taxRate;
return *this;
}
SoldBook calcSubtotal()
{
subtotal = (this->retail * qtySold) + tax;
return *this;
}
void setQtySold(int qty)
{
this->qtySold = qty;
}
int getQtySold()
{
return qtySold;
}
double getSubtotal()
{
return subtotal;
}
double getTotal()
{
return total;
}
InventoryBook getBook(InventoryBook book)
{
return book;
}
};
I wanted a SoldBook object to inherit all the data from InventoryBook without having to go to the extra trouble of creating a function that accepts the parent object as arguments and sets them in the child class ( SoldBooks )
ex.
void converter(char[] title, char[] isbn, ...etc)
{
this->bookTitle = title;
this->isbn = isbn;
etc...
}
Well I know how to do it the hard way but I just want the easiest way. Maybe something like
saleBooks[0] = allBooks[0];
do a constuctor take in the parent and member initialize it
public:
SoldBook(BookData bd)
:bookTitle(bd.title),
:isbn(bd.isbn),
:etc(etc),...
{}
then you can simply do
SoldBook soldBook = SoldBook(bd);
or create a vector for then
std::vector<SoldBook> soldBooks;
soldBooks.emplace_back(sb);
emplace back uses a constuctor call to avoid copying
and honestly i'd probably but the library into an unordered_map for easy key access

C++ OOP Abstract Class - Access violation writing location

I have an UserAcount class that has an abstract class ContBancar, and other class Banca which reads some users from a file (with method void Banca::citire_conturi()). When it reads the users, I get an error "Access violation writing location" in ContBancar at void setBal(double bal) { _balanta = bal; }. Thx for help !
PS : The file has only one line : 1CBS Dragos 0 dragos12! Gzpvia01= .
Also, i want to make a bank account system, with an user class that has an bank account class which inherits 3 types of a bank accounts, and a bank class which reads some users from a file or put them on it.
class UserAccount
{
private:
std::string _nume, _user, _pass;
std::string _cod_us;
std::shared_ptr <ContBancar> _cont;
public:
void setUser(std::string user) { _user = user; }
void setPass(std::string pass) { _pass = pass; }
void setNume(std::string nume) { _nume = nume; }
void setCodUs(std::string cod) { _cod_us = cod; }
void setContBal(double balanta) { (*_cont).setBal(balanta); }
std::string getUser() const { return _user; }
std::string getPass() const { return _pass; }
std::string getNume() const { return _nume; }
std::string getCodUs() const { return _cod_us; }
double getContBal() const { return (*_cont).getBal(); }
void setContBancar();
};
void UserAccount::setContBancar()
{
if (_cod_us == "1CBS")
_cont.reset(new ContBancarSilver());
else if (_cod_us == "2CBG")
_cont.reset(new ContBancarGold());
else
_cont.reset(new ContBancarDiamond());
}
class ContBancar
{
protected:
double _balanta;
public:
void setBal(double bal) { _balanta = bal; }
double getBal() { return _balanta; }
virtual bool depozitare(unsigned int) = 0;
virtual bool retragere(unsigned int) = 0;
};
class Banca
{
private:
std::vector<UserAccount> vec;
public:
void citire_conturi();
};
void Banca::citire_conturi()
{
std::ifstream file;
file.open("Baza_Date.txt");
UserAccount temp;
std::string cod, nume, user, pass;
double balanta;
while (file >> cod >> nume >> balanta >> user >> pass)
{
temp.setCodUs(cod);
temp.setNume(nume);
temp.setContBal(balanta);
temp.setUser(user);
temp.setPass(pass);
vec.push_back(temp);
}
file.close();
}
class ContBancarSilver : public ContBancar
{
private:
static constexpr unsigned int max_balanta = 5000;
static constexpr unsigned int max_depozitare = 2500;
static constexpr unsigned int max_retragere = 1000;
static constexpr double tax_retragere = 0.08;
static constexpr double bonus_depunere = 0.03;
static constexpr double bonus_tax_retragere = 0.05;
static constexpr unsigned int max_depozitari = 1;
static constexpr unsigned int max_retrageri = 1;
public:
virtual bool depozitare(unsigned int) override;
virtual bool retragere(unsigned int) override;
};
Based on available informationyou should fix your code like this:
class UserAccount
{
.....
void setCodUs(std::string cod) {
_cod_us = cod;
setContBancar();
}
void setContBal(double balanta) {
if (!_cont) setContBancar(); // lazy initialization
_cont->setBal(balanta);
}
...
};
void UserAccount::setContBancar()
{
if (_cod_us == "1CBS")
_cont = std::make_shared<ContBancarSilver>();
else if (_cod_us == "2CBG")
_cont = std::make_shared<ContBancarGold>();
else
_cont = std::make_shared<ContBancarDiamond>();
}
Note I do not understand what kind of logic you are implementing. This changes just ensured that _cont is initialized and up to date with _cod_us.
Please stop use explicitly new and delete. Everything can be created by std::make_shared and std::make_unique and containers like std::vector.

Trouble with printing C++ Hash Table

I'm pretty new to C++ and am trying to teach myself how to implement a hash table(I know I could use unordered_map, but I'm challenging myself). Right now I have a vector of structs(cell) that holds person-specific information. I have a PrintTable function that I want to use to print out each struct member of every item in the table. However, I can't seem to access the specific members of the struct(cell). What am I doing wrong here?
#include <iostream>
#include <string>
#include <vector>
struct cell
{
std::string name;
int age;
std::string weapon;
};
class HashTable
{
private:
std::vector<cell> *table;
int total_elements;
int getHash(int key)
{
return key % total_elements;
}
public:
HashTable(int n)
{
total_elements = n;
table = new std::vector<cell>[total_elements];
}
void SearchTheTable(int hashIndex);
void AddItem(std::string name, int age, std::string weapon);
void RemoveItem();
void PrintTable();
};
void HashTable::SearchTheTable(int hashIndex)
{
int x = getHash(hashIndex);
std::cout << x;
}
void HashTable::AddItem(std::string name, int age, std::string weapon)
{
cell newCell = { name, age, weapon };
table->push_back(newCell);
}
void HashTable::RemoveItem()
{
}
void HashTable::PrintTable()
{
for (int i = 0; i < table->size; i++)
{
std::cout << table[i].name; // Right here I get an error that says: class "std::vector<cell, std::allocator<cell>>" has no member "name".
}
}
int main()
{
HashTable theTable(5);
theTable.AddItem("Ryan", 27, "Sword");
theTable.AddItem("Melony", 24, "Axe");
theTable.PrintTable();
}

How do I define and set a a pointer to a 2d array that's passed twice in the middle class

I have an array in my MainProcessor
float waveforms[2][1080] = { {0}, {0} };
And I pass it to a SynthVoice like this:
osc1Voice->setWavetable(waveforms, 0); //[1]
osc2Voice->setWavetable(waveforms, 1);
There I read it like this in SynthVoice.h:
typedef float array_of_wavetable[1080];
void setWavetable(array_of_wavetable* waveform, int number)
{
wavetable = waveform;
id = number;
}
so i can use it like this in my SynthVoice class:
wavetable[id][first_sample + int(phase_0)]
Now I have moved [1] in a new class (OscilatorProcessor.h) and I want to set a pointer from MainProcessor -> OscillatorProcessor -> SynthVoice in a way that I can use it as wavetable[id][phase].
Now I don't know how to pass it from my MainProcessor to my OscillatorProcessor in the middle. So I can read it in the same way in the SynthVoice class.
I hope this made sense. Thank you for your time
edit: minimal reproducible example
#include <iostream>
typedef float array_of_wavetable[1080];
class SynthVoice
{
public:
void setWavetable(array_of_wavetable* waveform, int number)
{
wavetable = waveform;
id = number;
}
void outputWavetable()
{
for(int i = 0; i < 1080; i++)
{
std::cout << wavetable[id][i];
}
}
private:
array_of_wavetable * wavetable;
int id;
};
class OscillatorProcessor
{
public:
void setWavetable(array_of_wavetable * waveform, int number)
{
wavetable = waveform;
id = number;
}
void sendWaveToVoice()
{
SynthVoice voice;
voice.setWavetable(wavetable, id);
voice.outputWavetable();
}
private:
array_of_wavetable * wavetable;
int id;
};
int main() {
float waveform_templates[4][1080] = { {0}, {0}, {0}, {0} };
OscillatorProcessor oscillator;
oscillator.setWavetable(waveform_templates, 2);
return 0;
}

default value for a pointer parameter

I'm trying to create a class for employees, and have a problem with its constructor.
My class looks like that (please note the name parameter which is char* type):
class Employee {
int id;
char * name ;
float salary;
int hours;
int extra;
public:
//constructor
Employee(int, char *, float, int, int);
//Getters and Setters:
void setId(int a) { id = a; }
int getId() { return id; }
void setName(char * c) { name = c; }
char * getName() { return name; }
void setSalary(float f) { salary = f; }
float getSalary() { return salary; }
void setHours(int h) { hours = h; }
int getHours() { return hours; }
void setExtra(int e) { extra = e; }
int getExtra() { return extra; }
};
I built a constructor and I want it to have default parameters, and I don't know how to deal with the name parameter to have a default of let's say "unknown".
This is the constructor:
Employee::Employee(int i = 123456789, char * na, float sal = 30, int ho = 45, int ex = 10)
{
id = i;
name = na;
salary = sal;
hours = ho;
extra = ex;
}
You can use a character array, and initialise the array to point to the first element of the array. You can store the array for example as a static member:
// in the class definition
inline static char default_name[] = "unknown";
// in argument list of the constructor
... char * na = default_name, ...
Although, you may want to consider whether it makes sense for name to be pointer to non-const. Perhaps a pointer to const would suffice. In such case, you could initialise it to point to the literal "unknown" directly.
A cleaner version
class Employee {
int id = 0;
char *name = nullptr;
float salary = 0.0;
int hours = 0;
int extra = 0;
And you don't need to have constructors, this depends on the case, but you get the idea that by initializing the variables on the definition you reduce the inconsistency of having multiples constructors for example