A program that stores a phone company's consumers data in a linked list. At the end it displays the bill for each human. I have the following codes:
class BaseTypeOfContract
{
private:
int minutePrice;
int SMSPrice;
public:
void setminutePrice(int x) { minutePrice = x; }
void setSMSPrice(int x) { SMSPrice = x; }
virtual int calculateBill(int talkedMinutes, int sentSMS) = 0;
int getminutePrice() const { return minutePrice; }
int getSMSPrice() const { return SMSPrice; }
};
class SMSBaseType : public BaseTypeOfContract
{
private:
int freeSMS;
public:
SMSBaseType(int minutePrice, int SMSPrice, int freeSMS)
{
setminutePrice(minutePrice);
setSMSPrice(SMSPrice);
setfreeSMS(freeSMS);
}
public:
void setfreeSMS(int free) { this->freeSMS = free; }
virtual int calculateBill(int talkedMinutes, int sentSMS)
{
int billedSMS = (freeSMS > sentSMS) ? 0 : sentSMS - freeSMS;
return talkedMinutes * getminutePrice() + billedSMS * getSMSPrice();
}
};
class Base : public BaseTypeOfContract
{
public:
Base()
{
setminutePrice(30);
setSMSPrice(10);
}
virtual int calculateBill(int talkedMinutes, int sentSMS) { return talkedMinutes * getminutePrice() + sentSMS * getSMSPrice();}
};
class SMSMax : public SMSBaseType
{
public:
SMSMax() : SMSBaseType(20, 5, 150) {}
};
class MobiNET: public SMSBaseType
{
public:
MobiNET() : SMSBaseType(10, 15, 25) {}
};
Client's class:
class Client
{
public:
std::string name;
std::string phoneNumber;
BaseTypeOfContract* typeOfContract;
int talkedMinutes;
int sentSMS;
Client *next;
public:
Client(){}
Client(std::string n, std::string p, int bp, int ks) : name(n), phoneNumber(p), talkedMinutes(bp), sentSMS(ks) {}
void preSetPlan(std::string s)
{
if (s == "MobiNET")
this->typeOfContract = new MobiNET();
else if (s == "SMSMax")
this->typeOfContract = new SMSMax();
else this->typeOfContract = new Base();
}
std::string getname() const { return name; }
std::string getphoneNumber() const { return phoneNumber; }
void setname(std::string n) { name = n; }
void setphoneNumber(std::string pn) { phoneNumber = pn; }
void settalkedMinutes(int bp) { talkedMinutes = bp; }
void setsentSMS(int SSMS) { sentSMS = SSMS; }
int getBill() const { return this->typeOfContract->calculateBill(talkedMinutes, sentSMS); }
};
I read the data from 2 files. First file contains the name, phone number, type of contract. Second file contains the phone number, talked minutes and sent SMS.
Client* file_read_in()
{
std::ifstream ClientData;
ClientData.open("clients.txt");
Client *first = new Client;
first = NULL;
while (!ClientData.eof())
{
std::string name, phoneNumber, typeOfContract;
ClientData >> name;
ClientData >> phoneNumber;
ClientData >> typeOfContract;
std::ifstream ClientTalkedSent;
ClientTalkedSent.open("used.txt");
while(!ClientTalkedSent.eof())
{
std::string phoneNumber2;
ClientTalkedSent >> phoneNumber2;
if (phoneNumber2 == phoneNumber)
{
int talkedMinutes, sentSMS;
ClientTalkedSent >> talkedMinutes;
ClientTalkedSent >> sentSMS;
Client* tmp = new Client(name, phoneNumber, talkedMinutes, sentSMS);
tmp->preSetPlan(typeOfContract);
tmp->next = NULL;
if (first == NULL)
{
first = tmp;
}
else
{
Client *cond = first;
while (cond->next != NULL) cond = cond->next;
cond->next = tmp;
}
}
}
ClientTalkedSent.close();
}
ClientData.close();
return first;
}
And the main:
int main()
{
Client* first = file_read_in();
while(first != NULL)
{
std::cout << first->getname() << " " << first->getphoneNumber() << " " << first->getBill() << std::endl;
first = first->next;
}
return 0;
}
My problem that I should free the allocated memory but I got on idea how. Which class' destructor should do the dirty job. I would appreciate if someone could use my code, to show how the "destructor inheritance" works.
Sorry for my bad english and thanks for the help. This site helped me alot of times, but for this problem I did not find a solution.
If you have a pointer BaseTypeOfContract* typeOfContract; that is used to point to different derived classes, then BaseTypeOfContract needs to have a virtual destructor for delete typeOfContract to work.
And as Client seems to create the objects pointed to, it also ought to be responsible for cleaning them up. Either by using delete typeOfContract; in its destructor, or by storing a smart pointer to get the work done automatically.
The other part is that each Client stores a pointer to the next Client. That seems like not the best design. In real life it is not at all like each person knowing who is the next person that buys a cell phone in the same store. :-)
You would be much better of with a container, like std::vector<Client>, that would also handle the lifetime of the Client objects.
Related
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"};
...
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.
I have an abstract class "Mark" and it has a child class "Int_num". I also have a "Subject" class. I want a pointer to the address in the memory of the "Mark" class to be written to the "mark" parameter when calling its constructor. What should I do to make the mark pointer point to the "Mark" class?" occurred, after the compiler complaint about "expression must have class type" or something like that in mark.print_mark()?
class Mark {
private:
int mark;
public:
virtual void change_mark(int);
virtual void print_mark();
virtual int return_mark();
};
class Int_mark : public Mark {
private:
int mark;
public:
Int_mark();
Int_mark(int);
~Int_mark();
void change_mark(int = 0);
void print_mark() const;
int return_mark() const;
};
Int_mark::Int_mark() {
std::string str_mark;
std::cout << "New mark: ";
std::cin.ignore();
std::getline(std::cin, str_mark);
str_mark = ltrim(rtrim(str_mark));
int new_mark;
try {
new_mark = stoi(str_mark);
} catch(...) {
std::cout <<"wq";
mark = 1;
return ;
}
try {
if((new_mark < 1) || (new_mark > 5))
throw 1;
else
mark = new_mark;
} catch(int a) {
std::cout << "qw" << std::endl;
mark = 1;
}
}
void Int_mark::print_mark() const {
std::cout << "Mark: " << mark << std::endl;
}
Subject
#include "Mark.h"
#include <string>
#include <vector>
class Subject {
private:
std::string name_subject;
std::string type_subject;
unsigned hour_subject = 0;
void *mark = nullptr;
public:
Subject();
Subject(std::string, int);
Subject(std::string, bool);
~Subject();
void change_mark(unsigned);
void change_mark(bool);
void rename_subj(std::string);
void add_hour(unsigned);
};
Subject::Subject() {
std::string name_sub;
std::cout << "Введите название предмета: ";
getline(std::cin, name_sub);
name_sub = split_string(name_sub);
name_subject = name_sub;
int select = 2;
if(select == 1) {
type_subject = "Bool";
//mark = new Bool_mark();
} else {
type_subject = "Int";
mark = new Int_mark();
//What should I do to make the mark pointer point to the "Mark" class?
mark.print_mark();
}
}
main
#include "subject/Subject.h"
using namespace std;
int main() {
Subject q;
}
What am I doing wrong? How should I do this?
The pointer mark is of type void *. You could cast it with
static_cast<Int_mark*>(mark)
and call the function with
static_cast<Int_mark*>(mark)->print_mark();
But usually in OOP mark would be a pointer to the base class
Mark *mark = nullptr;
Now you can check for errors with
mark = new Int_mark();
auto *m = dynamic_cast<Int_mark*>(mark);
if (m)
m->print_mark();
Remember the virtual destructor in the base class
virtual ~Mark();
When to use virtual destructors?
Here is a fixed version of your code:
#include <iostream>
#include <string>
#include <vector>
class Mark {
public:
virtual ~Mark() = default;
//virtual void change_mark(int) = 0;
virtual void print_mark() const = 0;
//virtual int return_mark() const = 0;
};
class Int_mark : public Mark {
private:
int mark;
public:
Int_mark();
Int_mark(int);
~Int_mark() override = default;
//void change_mark(int = 0) override;
void print_mark() const override;
//int return_mark() const override;
};
Int_mark::Int_mark() {
std::string str_mark;
std::cout << "New mark: ";
std::cin.ignore();
std::getline(std::cin, str_mark);
//str_mark = ltrim(rtrim(str_mark));
int new_mark;
try {
new_mark = stoi(str_mark);
} catch(...) {
std::cout <<"wq";
mark = 1;
return ;
}
try {
if((new_mark < 1) || (new_mark > 5))
throw 1;
else
mark = new_mark;
} catch(int a) {
std::cout << "qw" << std::endl;
mark = 1;
}
}
void Int_mark::print_mark() const {
std::cout << "Mark: " << mark << std::endl;
}
class Subject {
private:
std::string name_subject;
std::string type_subject;
unsigned hour_subject = 0;
Mark *mark = nullptr;
public:
Subject();
Subject(std::string, int);
Subject(std::string, bool);
~Subject();
void change_mark(unsigned);
void change_mark(bool);
void rename_subj(std::string);
void add_hour(unsigned);
};
Subject::Subject() {
std::string name_sub;
std::cout << "Введите название предмета: ";
getline(std::cin, name_sub);
//name_sub = split_string(name_sub);
name_subject = name_sub;
int select = 2;
if(select == 1) {
type_subject = "Bool";
//mark = new Bool_mark();
} else {
type_subject = "Int";
mark = new Int_mark();
auto *m = dynamic_cast<Int_mark*>(mark);
if (m)
m->print_mark();
}
}
Subject::~Subject() {
delete mark;
}
int main() {
Subject q;
}
Since I did not correctly understand the question in the first place, here a way how you can call the member function of base class Mark by object of derived class Int_Mark:
Int_mark *mark = new Int_mark();
mark->print_mark(); // calls member of the class Int_mark
mark->Mark::print_mark(); // calls member of the class Mark
Make sure that Mark::print_mark() is also defined and not just Int_mark::print_mark()
My header file
class Roster {
private:
Degree degree = NETWORK;
int addFlag = 0;
Student* classRosterArray[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
public:
void add(string studentID, string firstName, string lastName, string emailAddress,
int age, int daysToComplete1, int daysToComplete2, int daysToComplete3, Degree degreeProgram);
void remove(string studentId);
void printAll();
void printByDegreeProgram(int degreeProgram);
void printDaysInCourse(string studentId);
void printInvalidEmails();
Student* getClassRosterArray();
~Roster();
};
My getter method in CCP file
Student* Roster::getClassRosterArray() {
return *classRosterArray;
}
My main() in CCP
for (int k = 0; k < 5; k++) {
cout << "Student ID :: " << roster.getClassRosterArray()[k].getStudentId() << endl;
}
And it only takes out the first Student object, for the second index in array is empty....
Pleaese help! it is my first trying C++.!!
I will propose this change :
Student* getClassRosterArray( int ) ;
...
Student* Roster::getClassRosterArray(int id) {
return classRosterArray[id];
}
...
for (int k = 0; k < 5; k++) {
cout << "Student ID :: " << roster.getClassRosterArray(k)->getStudentId() << endl;
}
To retrieve the member without losing its size information, you might do
class Roster {
private:
Student* classRosterArray[5] = { nullptr, nullptr, nullptr, nullptr, nullptr };
// ...
public:
auto getClassRosterArray() -> Student* (&)[5] { return classRosterArray;}
// ...
};
Ugly syntax :/
std::array<Student*, 5> has more regular syntax:
class Roster {
private:
std::array<Student*, 5> classRosterArray{{ nullptr, nullptr, nullptr, nullptr, nullptr }};
// ...
public:
std::array<Student*, 5>& getClassRosterArray() { return classRosterArray;}
// ...
};
As Student seems not polymorphic, not using pointer seems even simpler with std::vector:
class Roster {
private:
std::vector<Student> classRosterArray;
// ...
public:
std::vector<Student>& getClassRosterArray() { return classRosterArray;}
// ...
};
You declare an array of Student*, in other words you declare a Student**.
The get method return the a Student* and not a Student** or better a Student*[].
This cause you problem. In other words you return only the first element of the array.
My code:
class item{
int plu;
char * name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = copyStr(p); }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
char*getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
item(){
name = nullptr;
}
~item(){
delete name;
}
};
class puItem : public item{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
class nodeU{
puItem fruit;
nodeU * next;
public:
nodeU * getNext(){ return next; }
puItem getFruit(){ return fruit; }
void setNext(nodeU * g){ next = g; }
void setFruit(puItem g) { fruit = g; }
nodeU(){
next = nullptr;
}
};
class linkedListU{
nodeU * head;
int size;
public:
nodeU * getHead(){
return head;
}
void setHead(nodeU * n){
head = n;
}
//Append
void appendNode(nodeU * n){
if (head == nullptr){
head = n;
}
else{
nodeU * iter = head;
while (iter){
iter = iter->getNext();
}
iter->setNext(n);
}
size++;
}
linkedListU()
{
head = nullptr;
size = 0;
}
puItem * pluLookup(int g){
nodeU * iter = head;
while (iter)
{
if ((iter->getFruit()).getPlu() == g)
return &(iter->getFruit());
iter = iter->getNext();
}
return nullptr;
}
};
void checkout(linkedListP, linkedListU);
linkedListU unitList;
linkedListP poundList;
nodeU * inputU=new nodeU;
int main()
{
ifstream infile;
ofstream outfile;
int tempPlu;
string tempName;
bool tempType;
double tempPrice, tempInv;
infile.open("products.txt");
puItem unit;
infile >> tempPlu;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempName;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempType;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempPrice;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempInv;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
if (tempType == 0){
unit.setInventory(tempInv);
unit.setName(tempName.c_str());
unit.setPLU(tempPlu);
unit.setType(tempType);
unit.setPrice(tempPrice);
inputU->setFruit(unit);
unitList.appendNode(inputU);
}
checkout(poundList, unitList);
system("pause");
return 0;
}
void checkout(linkedListU p){
int key = -10;
puItem * searchU=nullptr;
int counter = 0;
double total = 0;
double amount;
cout << "Enter the plu for the item you want or enter 0 to exit: ";
cin >> key;
while (key < 0)
{
cout << "\nInvalid input please re enter: ";
cin >> k
searchU = p.pluLookup(key);
}
while (key)
{
When it gets to the plu lookup it throws the error and I cant seem to find out why.
I know that that is error is for deleting something twice but I couldnt find any instance of that in this code.
There are a lot of issues with your code, where most of them are due to your classes not being safely copyable (they lack a user-defined copy constructor and assignment operator, and destructor). Please see the rule of 3:
What is The Rule of Three?
Your checkout function has the following prototype:
void checkout(linkedListU p){
This means that you are passing linkedListU by value. Since linkedListU failed to follow the rule of 3, when you pass this type by value, you will invoke the compiler-defined copy constructor which only makes shallow copies, thus causing undefined behavior.
Your linked list class has members that are pointers to dynamically allocated memory, and they need to be properly handled by following the Rule of 3 at the link above. Since you failed to do that, passing by value cannot be done safely.
To address this issue, you can pass the linked list by reference, not by value:
void checkout(linkedListU& p){
This will stop the copying to occur, but it really doesn't address the underlying issue of the rule of 3 not being used in any of your classes.
For example, your puItem is being returned by value in the puItem::getFruit function, and also passed by value in the puItem::setFruit function. Calling these functions without any changes also invokes undefined behavior due to these classes not being safely copyable (also due to you using members that point to dynamically allocated memory).
To address this issue, the first thing you can do is change the base class item to use std::string name; instead of char *name;. This makes item now a copyable class without having to write user-defined copy operations or to have a destructor that needs to delete name;. The reason is that once std::string is used, all of your members in item can be copied without user intervention. The compiler default version would suffice.
class item
{
int plu;
std::string name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = p; }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
std::string getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
};
Note that there is no need for a destructor. Now, when puItem is derived from this class, puItem is also now safely copyable, and you can pass and return puItem by value:
class puItem : public item
{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
Making these changes totally eliminates usage of these classes from causing heap errors, double deletion errors, or memory leaks. Any further errors concerning memory issues are now focused on your linked list class (which uses dynamically allocated memory). So the least, the problem is narrowed down by a huge amount and is now focused.