Thread: Destructor Problem

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    14

    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;
    	}
    };

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    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.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    14
    please, can you suggest a constructor so that make it work?

  4. #4
    Registered User
    Join Date
    Nov 2010
    Posts
    8
    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)
    delete(head);
    }

    Class Node
    {
    if(next)
    delete(next)
    if(prev)
    delete(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).

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    14
    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

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed