4 Replies - 952 Views - Last Post: 08 April 2012 - 09:38 AM Rate Topic: -----

#1 Duaa Zahi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 30
  • Joined: 19-March 12

problem in the Destructor

Posted 08 April 2012 - 06:56 AM

Hi,
We were asked to create a class that stores some information about a person. e.g, Name, Gender and Address.
the following codes are the headers of two classes; person and address, and their implementations.
My problem is at the end of the program when it is terminating. The destructor is called twice to delete the same object so i get a debug assertion failure. Why does the program behave this way? and why the first thing it does is entering the destructor even before creating any objects ??? :S

another small question, when the user enters the phone number , it should be 14 digit number, why it discards the last number although the array size is 15?

//----------------------------------address.h--------------------//
#ifndef Address_H
#define Address_H
#include <iostream>
using namespace std;
#include <cstring>
const int MAXCHR=50; 
const int PHONE=14; 
class Address{
public :
	Address();
	Address( int, char*, char*, char*);
	~Address(); 
	int GetStreetNumber() const; 
	char* GetStateName() const; 
	char* GetCountry() const ; 
	char* GetPhoneNumber() const; 
	void SetStreetNumber( int );
	void SetStateName( char* ); 
	void SetCountry( char* ); 
	void SetPhoneNumber( char* ); 
	void PrintAddress(); 
private: 
	int streetNumber; 
	char* stateName; 
	char* country; 
	char* phoneNumber; 
}; 
#endif


//------------------------------person.h--------------------------//
#ifndef Person_h
#define Person_h
#include <iostream>
#include "address.h"
using namespace std;
const int MAXG=6; 
class Person
{
public:
	Person();
	Person(const char * n, const char * g, const  Address & ad);
	Person(const Person & f);
	void setName(char * n);
	void setType(char * n);
	void setAds( Address& ad ); 
	char * getName();
	char * getType();
	Address getAds();
	void printPersonDetails();
	~Person();
private:
	char * name;
	char * gender; 
    Address ads;
      };
#endif


//------------------------------Address.cpp-----------------------------//
#include "address.h"
int i=0;
Address::Address() //Default Constructor of class Address
{
	streetNumber=1;
	stateName=new char [MAXCHR+1]; 
	strcpy(stateName, "Nablus"); 
	country=new char [MAXCHR+1]; 
	strcpy(country, "Palestine"); 
	phoneNumber=new char [PHONE+1]; 
	strcpy(phoneNumber, "00197098989897"); 
}
//Construstor with passed arguments that sets data members to user's input
Address::Address( int strNo, char* stateN, char* con, char* phone)
{
	streetNumber=strNo;
	stateName=new char [MAXCHR+1]; 
	strcpy(stateName, stateN); 
	country=new char [MAXCHR+1]; 
	strcpy(country, con); 
	phoneNumber=new char [PHONE+1]; 
	strcpy(phoneNumber, phone); 
}
Address::~Address() //Destructor
{
	delete [] stateName;
	delete [] country; 
	delete [] phoneNumber; 
	cout<<"Address destructor"<<i<<endl;
	i++; 
}
//inline function implementation for get and set functions to get and set data members
int Address::GetStreetNumber() const {	return streetNumber; }
char* Address::GetStateName() const {  return stateName;   }
char* Address::GetCountry() const { return country;  } 
char* Address::GetPhoneNumber() const {return phoneNumber; }
void Address::SetStreetNumber( int strNo) { streetNumber=strNo; }
void Address::SetStateName( char* stateN) { strcpy(stateName, stateN); }
void Address::SetCountry( char* con ) { strcpy(country, con); } 
void Address::SetPhoneNumber( char* phone ) { strcpy( phoneNumber, phone);} 
void Address::PrintAddress() //prints Address details of a particular person
{
	cout<<"Address: "<<streetNumber<<", "<<stateName<<", "<<country<<". ";
	cout<<"phone no. "<<phoneNumber<<endl;
}



//------------------------person.cpp---------------------------//
#include "person.h" 
int j=0;
Person::Person() //Default Constructor
{
	name=new char [MAXCHR+1]; 
	strcpy(name, "Khaled"); 
	gender=new char [MAXG+1];
	strcpy(gender, "male"); 
	Address defaultAddress;
}
Person::Person(const char * n, const char * g, const Address& ad ) //Constructor with passed arguments
{
	name=new char [MAXCHR+1]; 
	strcpy(name, n);
	gender=new char [MAXG+1];
	if ( strcmp(g, "male")== 0 || strcmp(g, "female")== 0) //checking gender
		strcpy(gender, g); 
	else 
		{
			cout<<"Error."; 
			exit(0); }
	ads=ad;
}
Person::Person(const Person & f) //copy constructor 
{
	name=new char [MAXCHR+1]; 
	gender=new char [MAXG+1];
	strcpy( name, f.name);  
	strcpy( gender, f.gender); 
	ads= f.ads;  
	cout<<"The copy constructor is called\n"; 
}
void Person::setName(char * n) //sets name with user's input
{
	strcpy( name, n);
}
void Person::setType(char * n) //sets the gender with user's input
{
	if ( strcmp(n, "male")==0 || strcmp(n, "female")==0) //checking gender
		strcpy(gender, n); 
	else 
		{
			cout<<"Error."; 
			exit(0); } 
}
void Person::setAds( Address& ad ) //sets the address from the user
{
	ads.SetStreetNumber( ad.GetStreetNumber());
	ads.SetStateName( ad.GetStateName()); 
	ads.SetCountry( ad.GetCountry()); 
	ads.SetPhoneNumber( ad.GetPhoneNumber()); 
}
char * Person::getName() {	return name;   } //returns the name
char * Person::getType() {	return gender; } //returns the gender
Address Person::getAds() { 	return ads;    } //returns the address
void Person::printPersonDetails() //prints the details of a person
{
	cout<<"Name: "<<name<<", Gender:"<<gender<<endl;
	ads.PrintAddress(); 
}
Person::~Person() //person class destructor
{
	delete [] name; 
	delete [] gender;
	cout<<"Person Destructor"<<j<<endl;
	j++;  
}



//------------------------------driver.cpp----------------------------//
#include "address.h"
#include "person.h"
 
void main(){
	Person a; 
	a.printPersonDetails(); 
	Address duaaAds( 23, "Dubai", "United Arab Emirates", "00971560000000"); 
	Person b( "Duaa" , "female", duaaAds ); 
	b.printPersonDetails(); 
	Person c;
	cout<<"Enter a new person to the list: \n";
	int streetno; 
	char * n=new char [MAXCHR+1];
	char * g=new char [MAXG+1];
	char * state=new char [MAXCHR+1]; 
	char * country=new char [MAXCHR+1]; 
	char * phone= new char [PHONE+1]; 
	cout<<"enter name: "; 
	cin>>n;
	c.setName( n ); 
	cout<<"enter gender: ";
	cin>>g;
	c.setType( g );
	cout<<"enter street no. : "; 
	cin>>streetno; 
	cin.ignore();
	cout<<"enter state name: "; 
	cin.getline( state, MAXCHR);
	cout<<"enter country name: "; 
	cin.getline( country, MAXCHR); 
	cout<<"enter phone number: "; 
	cin.getline( phone, PHONE); 
	Address newAds( streetno, state, country, phone); 
	c.setAds( newAds) ; 
	c.printPersonDetails(); 
	delete [] n;
	delete [] g;
	delete [] state; 
	delete [] country; 
	delete [] phone; 
}




i know it is long question but i really tried my best to know what's wrong but i couldn't ...
thanks in advance for helping me :)

Is This A Good Question/Topic? 0
  • +

Replies To: problem in the Destructor

#2 jimblumberg  Icon User is offline

  • member icon


Reputation: 3993
  • View blog
  • Posts: 12,321
  • Joined: 25-December 09

Re: problem in the Destructor

Posted 08 April 2012 - 07:22 AM

Quote

another small question, when the user enters the phone number , it should be 14 digit number, why it discards the last number although the array size is 15?

Are you perhaps forgetting to leave room for the end of string character ('\0')?

Quote

and why the first thing it does is entering the destructor even before creating any objects ??? :S

But you are creating objects, look at your Person default constructor.
Person::Person() //Default Constructor
{
	name=new char [MAXCHR+1];
	strcpy(name, "Khaled");
	gender=new char [MAXG+1];
	strcpy(gender, "male");
	Address defaultAddress;
}


You create an instance of an Address in this function, which is local to this function, so when this function returns this instance is destructed.

Your problem with the assert is in your Address destructor, with the phoneNumber deletion. Why are you using dynamic memory for this variable? You know the size of this variable, 14 why not just use a normal statically allocated array (phoneNumber[14])?

You may also want to consider changing from the C-strings to std::string, this will greatly simplify your program.

But since you are using pointers in your classes you should be defining your copy, and assignment operators as well as your destructors.


Jim
Was This Post Helpful? 0
  • +
  • -

#3 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2891
  • View blog
  • Posts: 10,025
  • Joined: 08-August 08

Re: problem in the Destructor

Posted 08 April 2012 - 09:04 AM

And since you're using C++ you could drop the dynamic allocation altogether and use vectors. Then you don't have to worry about allocating or deallocating memory since the vectors will do that for you.
Was This Post Helpful? 1
  • +
  • -

#4 Duaa Zahi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 30
  • Joined: 19-March 12

Re: problem in the Destructor

Posted 08 April 2012 - 09:25 AM

Thank you both ...
but am really sorry Jim ..
i didn't understand what are you trying to say about the destructor .. i thought that the desctructor is only called at the ending } in the main. now this does not make sense to me .. why it destroys the instance how does it keep the information ??

Quote

Your problem with the assert is in your Address destructor, with the phoneNumber deletion. Why are you using dynamic memory for this variable? You know the size of this variable, 14 why not just use a normal statically allocated array (phoneNumber[14])?

i tried to make an array: phone[14] , but it was messy.. i got alot of errors.. and i don't know vectors yet.. I know am annoying ..but please can you tell me where to make the changes.
i get errors in get and set functions while passing the array .. also there is an error that says illegal digit '9' for base '8' ??!!

Quote

You may also want to consider changing from the C-strings to std::string, this will greatly simplify your program.

i think what are you referring to is the class strings if am not mistaken .. i didn't take it yet.. if it is simpler as you say .. i wonder why they like to waste our time in study stuff that are harder to program while there are simpler ways to do it ..
Thanks ..
Duaa
Was This Post Helpful? 0
  • +
  • -

#5 jimblumberg  Icon User is offline

  • member icon


Reputation: 3993
  • View blog
  • Posts: 12,321
  • Joined: 25-December 09

Re: problem in the Destructor

Posted 08 April 2012 - 09:38 AM

Quote

i didn't understand what are you trying to say about the destructor .. i thought that the desctructor is only called at the ending } in the main

A class destructor is called any time the class goes out of scope. In your case you declare an instance of your Address class in your Person constructor, so when that constructor finishes any local variable is deleted (destructed). So your Address class destructor will be called. I don't really see why you are even creating an instance of your Address class in the Person constructor in the first place, but that is the reason you are seeing the destructor being called.

Quote

i tried to make an array: phone[14] , but it was messy.. i got alot of errors..

If you were getting a lot of errors when you were using a statically allocated array, you probably are going to have even more problems when dealing with a dynamically allocated array. Go back to the statically allocated arrays and fix the problems. Using dynamically allocated arrays is much more cumbersome and error prone in my opinion, and should not be used until you are very familiar with statically allocated arrays.

Quote

.. also there is an error that says illegal digit '9' for base '8' ??!!

That means that you have an integral constant starting with a 0, a leading 0 on an integral constant (09) indicates to the compiler that the constant is using the Octal number base. Remove the leading zero.

Quote

i get errors in get and set functions while passing the array

When you are having compile errors post the complete error messages, exactly as they appear in your development environment.

Jim
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1