-
Destructor Problem
Hi everyone
I have been doing a program about computing the remaining cost in some Store,
in accounting called ending inventory, and it is a homework from my instructor to use the Stack,List and Queue in one program, anyway
the program work without the destructor of List Class, but with it, it doesn't work.
I think my problem with the " work ( ) " member function!! but i don't know how??
Please help me...
Code:
#include <iostream>
#include "iomanip"
using namespace std;
#include "conio.h"
#include "list_stack_queue.h"
#include "process.h"
#include "start_the_program.h"
void main()
{
StartTheProgram start;
start.work();
start.PrintTable();
getch();
}
Code:
class StartTheProgram
{
private:
int it,num_of_current_items;
float pr;
char op,f;
int o;
ulist<int> Items;
ulist<float> Price;
ulist<char> Operation;
public:
float co;
StartTheProgram()
{
num_of_current_items=0;
f='a';
o=1;
}
void work()
{
while(f=='a')
{
begin:
cout<<"OPERATION "<<o<<"\n___________"<<endl;
cout<<"\nEnter the operation (p=purchase or s=sale): \n";
cin>>op;
if(op=='s')
Price.Insert(0);
if(op=='p')
{
cout<<"\nEnter the price of purchase: \n";
cin>>pr;
Price.Insert(pr);
}
cout<<"Enter the number of items: \n";
cin>>it;
//Number of current items in the stor----------
if(op=='p')
num_of_current_items+=it;
else
num_of_current_items-=it;
Items.Insert(it);
Operation.Insert(op);
cout<<"\n\t\t\t\t\t-> To do that once again press: a\n\t\t\t\t\t-> Else press : n \n";
cin>>f;
cout<<"\n-------------------------------------------------------------\n";
o++;
}
Process<float> process(Items,Price,Operation,num_of_current_items);
float final_cost=0;
process.TransferToStack();
co=process.Cost();
cout<<"The Remaining Cost In The Store Is: "<<co;
cout<<"\n-------------------------------------------------------------\n";
cout<<"\n\t\t\t\t\t-> To enter new values press : a\n\t\t\t\t\t-> To View The Table And Exit Press Any Key \n";
char m;
cin>>m;
if(m=='a')
goto begin;
cout<<"\n********************************************************************************************\n";
cout<<"\n********************************************************************************************\n";
}
void PrintTable()
{
queue<char*> Qoperation;
queue<int> Qitems;
queue<float> Qprice;
int aa=Operation.Length();
for(int i=0;i<aa;i++)
{
if(Operation.ItemValue(i) == 'p')
Qoperation.enqueue("Purchase");
else
Qoperation.enqueue("Sale");
Qprice.enqueue(Price.ItemValue(i));
Qitems.enqueue(Items.ItemValue(i));
}
cout<<"\n\n\n\t\t\t*****************\n\t\t\tTable Of Contents\n\t\t\t*****************\n\n\n";
//cout<<"\t\t IN\t OUT";
//cout<<"\n\t _ _ _ _ _ _ _ _ _ _ _ _\n";
cout<<"\nOPERATION PRICE NUMBER NUMBER REMAINING COST";
cout<<"\n\t OF OF OF ";
cout<<"\n\t PURCHASE PURCHASE SOLD ";
cout<<"\n\t ITEM ITEMS ITEMS ";
cout<<"\n_________ _________________ ______ ______________\n\n";
while(!Qoperation.IsEmpty())
{
if(Qoperation.ReturnDequeue() == "Sale")
{
if(Qoperation.LastOne())
{
cout.fill(' ');
cout.width(39);
cout<<left<<Qoperation.dequeue();
cout.width(12);
cout<<left<<Qitems.dequeue()<<co<<endl<<endl;
Qprice.dequeue();
}
else
{
cout.fill(' ');
cout.width(39);
cout<<left<<Qoperation.dequeue()<<Qitems.dequeue()<<endl<<endl;
Qprice.dequeue();
}
}
else
{
if(Qoperation.LastOne())
{
cout.fill(' ');
cout.width(15);
cout<<left<<Qoperation.dequeue();
cout.width(10);
cout<<left<<Qprice.dequeue();
cout.width(26);
cout<<Qitems.dequeue()<<co<<endl<<endl;
}
else
{
cout.fill(' ');
cout.width(15);
cout<<left<<Qoperation.dequeue();
cout.width(10);
cout<<left<<Qprice.dequeue();
cout.width(26);
cout<<Qitems.dequeue()<<endl<<endl;
}
}
}
}
};
Code:
template <class T>
class Process
{
private:
ulist<int> Items;
ulist<float> Price;
ulist<char> Operation;
float cost;
public:
stack<int> Sitem;
stack<float> Sprice;
stack<char> Soperation;
float cost_after_purchases;
int repetitions;
int num_of_store_items;
Process(ulist<int> it,ulist<float> pr,ulist<char> op,int num_of_current_items)
{
Items=it;
Price=pr;
Operation=op;
cost=0;
cost_after_purchases=0;
num_of_store_items=num_of_current_items;
}
void TransferToStack()
{
int num_of_s=Operation.FirstS();
int s=0,p=0;
int len=Items.Length();
while(p<len)
{
if(Operation.ItemValue(p) == 's')
s++;
if(Operation.ItemValue(p) =='s' && s != num_of_s)
{
p++;
continue;
}
Sitem.push(Items.ItemValue(p));
Sprice.push(Price.ItemValue(p));
Soperation.push(Operation.ItemValue(p));
p++;
}
}
float Cost()
{
if(Soperation.ReturnPop() == 'p')
{
cost_after_purchases+=(Sprice.ReturnPop()*Sitem.ReturnPop());
num_of_store_items-=(Sitem.ReturnPopPlus1());
while(Soperation.ReturnPop() == 'p')
{
cost_after_purchases+=Sitem.ReturnPop()*Sprice.ReturnPop();
num_of_store_items-=Sitem.ReturnPopPlus1();
}
}
if(!Soperation.IsEmptyR() && Soperation.ReturnPopPlus1()=='s')
{
Sitem.ReturnPop();
if(num_of_store_items <= Sitem.ReturnPop())
cost=(num_of_store_items * Sprice.ReturnPopMinus1());
else
{
int x=num_of_store_items;
ulist<int> arrItems;
ulist<float> arrPrice;
//reset
arrItems.Insert(Sitem.ReturnPopPlus1());
Sprice.ReturnPop();
arrPrice.Insert(Sprice.ReturnPop());
x-=Sitem.ReturnPopPlus1();
while(x >= Sitem.ReturnPop())
{
arrItems.Insert(Sitem.ReturnPopPlus1());
x-=Sitem.ReturnPopPlus1();
arrPrice.Insert(Sprice.ReturnPop());
}
arrItems.Insert(x);
arrPrice.Insert(Sprice.ReturnPop());
int r=0;
while(!arrItems.isempty())
{
cost+=(arrItems.ItemValue(r)*arrPrice.ItemValue(r));
r++;
}
}
}
Soperation.Clear();
Sitem.Clear();
Sprice.Clear();
float cost2=cost_after_purchases;
cost_after_purchases=0;
return cost+cost2;
}
};
Code:
template<class T>
class ulist
{
private:
int size,length,current;
T *ulistptr;
public:
ulist(int s=10)
{
size=s>0 && s<1000?s:10;
length=0;
ulistptr=new T[size];
}
/*~ulist()
{
delete[] ulistptr;
}*/
bool isfull()const{
return length==size;
}
int isempty()const{
return length==0;
}
int Insert(const T item)
{
if(!isfull())
{
ulistptr[length]=item;
current=length;
length++;
return 1;
}
else
return 0;
}
int FirstS()
{
int num_of_s=0;
for(int i=0;i<length;i++)
if(ulistptr[i] == 's')
num_of_s++;
return num_of_s;
}
T ItemValue(int i)
{
length--;
return ulistptr[i];
}
int Length()
{
return length;
}
};
-
At a quick glance I would say it doesn't work with the destructor in place because your ulist class does not implement a proper (or rather any) copy constructor. Your other bits of code include elements which result in (for example) a ulist object being passed by copy as a parameter to a function. When this happens, the copy constructor is called for the ulist object. Since you've neglected to define one, the compiler made up a default one which is doing a poor job. This is due to the class using a pointer member which never gets copied properly with a default version of the copy constructor, a simple copy is made of the value of the pointer such that the copy's pointer points to the same memory area that the originals pointer points to. When the copy's destructor is called at the end of the function it was passed into, it calls delete on the memory pointed to by that pointer - this is the same memory pointed to by the original. When it comes time for the original to be destroyed, the destructor again attempts to delete that same memory but it's already too late since it's been deleted already.
So... the moral of the story is that whenever you have a class with a raw pointer, you need to implement a proper copy constructor that does a deep copy and not just a shallow copy of the pointer's value.
-
please, can you suggest a constructor so that make it work?
-
Well, this may not be very helpful but I will not it anyways. I ran into the same problem that you are having with one of my programs in which I implemented a doubly linked list. My program would work as long as I did not have a destructor in my list class. The destructors that I had:
Class List
{
if(head)
}
Class Node
{
if(next)
if(prev)
}
I could not see the class T which is being used as the template up there so I don't know if what I had encountered is anything like your problem. But, I thought I would point it out. The problem with mine was that my list destructor would call the Node destructor on the head node which would then recursively call the node destructor on all the nodes after it. But, because in my Node destructor I had instructed it to delete both pointers after all the memory for the next pointers were deallocated I would end up in a recursive loop trying to delete the prev pointers which were spots of memory which had already been deallocated with the deletion pass of the next pointers (If that makes any sense to you).
-
yes,it's similar to my problem,but i used a simple List (just a dynamic array),
I think my problem with Work() member function,at the end of work() function the destructor is called,
I don't know why
so far i know the destructor is called in these situations :
when we explicitly type a delete keyword, when pass objects out of scope (temporary objects) and at the end of the block that the objects were created in it
Is there any other situations?
I think my problem is require an expert
by the way ,i use C++2008
-
Your program is not properly indented and uses goto, making it difficult to read. I suggest you fix that.
Now, ulist is a ticking time bomb because it uses a raw pointer and fails to either implement a copy constructor or assignment operator or disallow them.
The problem is that this. Say you create an instance A. A allocates memory.
Now you create B as a copy of A (ie ulist B(A)). B gets the same pointer as A.
B goes out of scope and releases memory. A goes out of scope, tries to release already freed memory and crashes.