default value for a pointer parameter - c++

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

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

the code doesn't display and doesn't run either

Below is a program that has class definitions for Item, Customer and Sales. The main simply creates object object of each class and test its member functions. Modify the main program such that it provides a menu driven interface where user can create objects of Item, Customer and a complete a sales transaction with the sales object.The program should also have an option for display the records of items,customers and sales.To make your program more useful,include file handling such that when objects are created for Items,Customers and Transaction,the user will be prompted to save the recordon the file or not.
here's the code it's not displaying anything pleasee help i'm running it by Dev c++
#include <conio.h>
#include <iostream>
#include <string.h>
using namespace std;
class Item {
int itemCode;
private:
double price;
double discount;
protected:
int qtyOnStock;
char *name;
public:
Item() {
itemCode = 0;
strcpy(name, "UNKNOWN");
price = 0;
discount = 0;
qtyOnStock = 100;
}
void setItemCode(int c) { itemCode = c; }
int getItemCode() { return itemCode; }
double getPrice() { return price; }
void setPrice(double p) { price = p; }
void setDiscount(double d) { discount = d; }
double getDiscount(double d) { return ((d < 20 ? d : 20) / 100 * price); }
void setName(char *n) { name = n; }
char *getName() { return name; }
void setQtyOnStock(int q) { qtyOnStock = q; }
int getQtyOnStock() { return qtyOnStock; }
};
class Customer {
private:
int id;
char *name;
char *contactNo;
int type;
public:
Customer() {
id = 0;
strcpy(contactNo, "No Num");
strcpy(name, "No Name");
type = 0;
}
void setId(int newId) { id = newId; }
int getId() { return id; }
void setName(char *n) { strcpy(name, n); }
char *getName() { return name; }
void setContactNo(char *c) { strcpy(contactNo, c); }
char *getContactNo() { return name; }
};
class Sales {
private:
Item item;
Customer cust;
char *date;
int qtySold;
public:
Sales() { date = "mm-dd-yyyy"; }
void setItem(Item newItem) { item = newItem; }
Item getItem() { return item; }
void setCustomer(Customer newCust) { cust = newCust; }
Customer getCustomer() { return cust; }
void setDate(char *newDate) { strcpy(date, newDate); }
char *getDate() { return date; }
void setQtySold(int newQty) { qtySold = newQty; }
int getQtySold() { return qtySold; }
};
int main() {
Item item1;
Customer cust1;
Sales sales1;
item1.setItemCode(143);
item1.setName("Ballpen");
item1.setPrice(12.5);
item1.setQtyOnStock(250);
cust1.setId(123);
cust1.setName("Juan dela Cruz");
sales1.setItem(item1);
sales1.setCustomer(cust1);
sales1.setDate("10-27-2018");
sales1.setQtySold(98);
item1.setQtyOnStock(item1.getQtyOnStock() - sales1.getQtySold());
system("cls");
cout << sales1.getItem().getName() << endl << item1.getQtyOnStock();
getch();
return 0;
}
The main and biggest proble is that you do C-style string handling with char* and even that in a wrong way.
If you would enable all warning in your compiler, it would already tell you the problems. My VS2019 gives 15 errors, 1 warning and 7 messages, when I try to compile your code. Please see:
So, the main problem is that you are using char* that are not initialzed, meaning they point to somehwere, and that you do not allocate memory to store your strings.
So all your strcpy functions will fail and probably crash your system. Also the assignments to a char* will fail in most cases.
You will overwrite some random memory.
All this can be immediately fixed, without big problems, if you would use std::string instead of char*. Because char* are that error prone, C++ introduced the std::string, so, please use it.
Sometimes you have C++ teachers that want you to use char*. Those teachers should be fired. But if you really need to use char*. Then you must allocate memory, before coping data.
Let us assume that you have a string "myName" and you want to copy that.
char* name{};
name = new char[strlen(myName)+1]; // +1 for the trailing '\0'
strcpy(name, myName);
// ...
// ...
// Do stuff
// ...
// ...
delete [] name; // Release memory at the end
But as said. Simply use std::string
Your program as is, cannot work. You need a major refactoring.
In your Item class:
protected:
int qtyOnStock;
char *name;
public:
Item() {
itemCode = 0;
strcpy(name, "UNKNOWN");
price = 0;
discount = 0;
qtyOnStock = 100;
}
name is an unitialized char pointer so copying to it will result in UB.
change char* name to std::string name, replace strcpy(...) name = "UNKNOWN".
Normally though you initialize member variables like this:
Item()
: itemCode(0), itemCode(0), name("UNKNOWN"), price(0), discount(0), qtyOnStrock(100)
{}
a newer compiler lets you initialize in other ways like when declared e.g.:
protected:
int qtyOnStock{100};
std::string name{"UNKNOWN"};
...

C++ Inheritance of functions, passing in arguments

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.

Pointers practice improvement

Hello! I wanted to learn more about pointers, so i wrote the following:
struct Data {
int day, month, year;
double hour;
};
class Movie {
protected:
string name;
Data data;
int requiredAge;
int freeSeats;
public:
Movie(){ }
Movie(string moviename, Data dat, int age, int seats) {
name = moviename;
data = dat;
requiredAge = age;
freeSeats = seats;
}
int getFreeSeats() { return freeSeats; }
~Movie(){ }
};
And then i initialize it into the main:
int _tmain(int argc, _TCHAR* argv[])
{
Data d; d.day = 12; d.hour = 16; d.month = 04; d.year = 2016;
Movie movie("Movie Name", d, 16, 35 );
system("pause");
return 1;
}
Why should i use pointers here and where?
The only place where it could make sense to use pointers here is for passing the struct to the constructor:
Movie(string moviename, Data* dat, int age, int seats) {
name = moviename;
data = *dat;
requiredAge = age;
freeSeats = seats;
}
This would avoid creating a complete copy of the struct when the constructor is called. Just passing the pointer is a bit cheaper.
While in C, this would be the only option, in C++ there is a better way: Use references:
Movie( const string& moviename, const Data& dat, int age, int seats) {
name = moviename;
data = dat;
requiredAge = age;
freeSeats = seats;
}
By the way, for the intarguments it is not useful to pass them by reference bacause they are not larger (in terms of bytes) than a pointer.
An even better version would use an initialization list:
Movie( const string& moviename, const Data& dat, int age, int seats)
: name(moviename), data(dat), requiredAge(age), freeSeats(seats) {}
(Thanks for the hint, #NathanOliver)

I can't display variables of different types included in array

I have to do a program for college.
I have 3 classes already declared in the statement of the problem.
First class:
class piesa_a{
protected:
int id;
char *tip;
int pret;
};
Second class:
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
};
Third class:
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
};
In main I need to create an array in which to store items such piesa_a, piesa_b, piesa_c. Then I have to sort items by price.
I have this code so far: http://pastebin.com/nx2FGSfe
The program is incomplete because it does not displays each item in the array.
I got stuck here. But if you display the array's elements when they are outside of it, it works.
SHORT: I have an error on line 143 and I want to solve it.
main.cpp:143:18: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
The code is here:
#include <cstdlib>
#include<iostream>
#include<string.h>
using namespace std;
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
piesa_a()
{
id = 0;
tip = new char[1];
pret = 0;
}
piesa_a(int aidi, char *typ, int pretz)
{
id = aidi;
tip = new char[strlen(typ)+1];
strcpy(tip,typ);
pret = pretz;
}
piesa_a&operator =(piesa_a alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
return *this;
}
virtual void afisare()
{
cout<<"\n Piesa A: "<<id<<" "<<tip<<" "<<pret;
}
};
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
piesa_b():piesa_a(){lungime = 0;bw = 0;}
piesa_b(float lg,bool bl, int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
lungime = lg;
bw = bl;
}
piesa_b&operator =(piesa_b &c)
{
id = c.id;
tip = new char[strlen(c.tip)+1];
strcpy(tip,c.tip);
pret = c.pret;
lungime = c.lungime;
bw = c.bw;
return *this;
}
void afisare()
{
piesa_a::afisare();
cout<<"impreuna cu piesa B: "<<lungime<<" "<<bw<<"\n";
}
};
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
nr = n;
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
piesa_c&operator =(piesa_c &alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
nr = alta.nr;
for(int i=0;i<alta.nr;i++)
buf[i] = alta.buf[i];
}
void afisare()
{
for(int i=0;i<nr;i++)
buf[i].afisare();
}
};
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
What's wrong?
In C++ (and current C), casts are almost always a sign that the programmer didn't know how to use the language as it is supposed to be used. If you need an array of 3 types of data, the cleanest solution is an array of objects of a class that is base to the 3. And if you want to display each item differently, you'll want to overload the << operator, so you just iterate over the array and go << on each item. Sorted by price means that the class includes a price field, and you use the sort from the standard template library, passing a comparison operation that just compares prices.