Using constructors

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 877 Views - Last Post: 12 April 2017 - 07:17 PM Rate Topic: -----

#1 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Using constructors

Posted 11 April 2017 - 08:09 PM

This is a pretty simple program that just finds the area and perimeter of a circle. I need to allow the user to enter either the radius of the circle, or the coordinates of the center of the circle, or both.

My problem is that although I can see my constructor (Oh, and this needs to be done using a default constructor and multiple constructors with parameters) has been called, it does not change the value of the private variables. I know my object goes out of scope, but if it is supposed to set the private variables why does it matter? Where am I going wrong? (if there is anything that is completely unnecessary it may be from the rest of the program. I just copied the parts related to this function that isn't working.)

Where am I going wrong? What is the correct way to set up my constructors to accomplish what I am trying to do?

#include <iostream>
using namespace std;

class Circles    
{
public:
   void setCenter(int x, int y);
   double findArea();   
   double findCircumference(); 
   void printCircleStats(); // This outputs the radius and center of the circle. 
   Circles(float r, int x, int y);  // Constructor
   Circles(float r);     
   Circles(int x, int y);
   Circles();               // Default constructor
   ~Circles();
private: 
   float  radius;
   int    center_x;
   int    center_y;
};      


const double PI = 3.14;

//Client section   

int main()
{
   char y_n; // user can enter y or n to specifying a value
   float  size; // user specified values for circle
	int	  x_coor,
		  y_coor;
   
   bool rad = false,
		coor = false;  // true if user enters data
		
			Circles sphere; // default constructor for user circle
	
	
   cout << "This program finds the area and circumference " << endl
		<< "of a circle. Type y to enter a value for radius " << endl
		<< "or no to use the default radius of 1." 			<< endl;
	cin	>> y_n;
	
	if(y_n == 'y' || y_n == 'Y')
	{
		cout << endl
			 << "Enter the radius:   ";
		 cin >> size;
		rad = true; 
	}
	cout << endl
		 << "Type y to enter x and y coordinates for the " << endl
		 << "center of the circle or n to use the default " << endl
		 << "of (0,0)." << endl;
	 cin >> y_n;
	 
	 	if(y_n == 'y' || y_n == 'Y')
	{
		cout << endl
			 << "Enter the x and y coordinates (in the order)"
			 << "separated by a space:   ";
		 cin >> x_coor >> y_coor;
		 coor = true;		 
	}
   
	if(rad == true && coor == true)
	{
		Circles sphere(size, x_coor, y_coor);
	}   

	else if(rad == true && coor == false)
	{
		Circles sphere(size);
	}   	
   
   	else if(rad == false && coor == true)
	{
		 Circles sphere(x_coor, y_coor);
	}   
	
	sphere.printCircleStats(); 
	cout << "The area of the circle is " << sphere.findArea() << endl;
	cout << "The circumference of the circle is "
	     << sphere.findCircumference() << endl;
		 
   return 0;
}

//Implementation section     Member function implementation

Circles::Circles()
{
    radius = 1;
   	center_x = 0;
	center_y = 0;
   
}


Circles::Circles (float r)       //non-default Constructor
{
	cout << "circles y n was called with " << r << endl;
	radius = r;
}

Circles::Circles (float r, int x, int y)       // Constructor
{
	cout << "circles y y was called with " << r << " " << x << " " << y << endl;
	radius = r;
	center_x = x;
	center_y = y;
}

Circles::Circles (int x, int y)       // Constructor
{
	cout << "circles n y was called with " << x << " " << y << endl;
	center_x = x;
	center_y = y;
}

// implement the findArea member function
double Circles::findArea()
{
	return PI * radius * radius;
}

// implement the findCircumference member function
double Circles::findCircumference()
{
	return 2 * PI * radius;
}


void Circles::printCircleStats()
// This procedure prints out the radius and center coordinates of the circle
// object that calls it.

{
   cout << "The radius of the circle is " << radius << endl;
   cout << "The center of the circle is (" << center_x 
        << "," << center_y << ")" << endl;
}

void Circles::setCenter(int x, int y)
// This procedure will take the coordinates of the center of the circle from 
// the user and place them in the appropriate member data.

{
   center_x = x;
   center_y = y;
} 

Circles::~Circles()
{
	cout << "This concludes the Circles class " << endl;
}



Is This A Good Question/Topic? 0
  • +

Replies To: Using constructors

#2 r.stiltskin  Icon User is offline

  • Poorly Educated
  • member icon

Reputation: 1950
  • View blog
  • Posts: 5,215
  • Joined: 27-December 05

Re: Using constructors

Posted 11 April 2017 - 08:36 PM

View Postklg52486, on 11 April 2017 - 11:09 PM, said:

I know my object goes out of scope, but if it is supposed to set the private variables why does it matter?

Because it's going out of scope.

At the end of main you're printing the stats for the object that you declared at the beginning of main with the default constructor. Any objects that you create in the if statements die at the end of the if statement, leaving the default object unchanged.
Was This Post Helpful? 1
  • +
  • -

#3 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 11 April 2017 - 08:44 PM

But how do I fix it? I am really struggling with classes and I've been trying to figure it out for hours. I tried

sphere = Circles(size, x_coor, y_coor);

sphere = Circles(size);



etc, but then if one of the variables isn't initialized, I just get garbage. Isn't that the point of the default? That the private variables should be initialized?
Was This Post Helpful? 0
  • +
  • -

#4 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 11 April 2017 - 08:54 PM

Or is there a way to keep it from going out of scope? I don't really understand why it goes out of scope, I just know that it does because my destructor was activated.
Was This Post Helpful? 0
  • +
  • -

#5 r.stiltskin  Icon User is offline

  • Poorly Educated
  • member icon

Reputation: 1950
  • View blog
  • Posts: 5,215
  • Joined: 27-December 05

Re: Using constructors

Posted 11 April 2017 - 09:00 PM

The same scope rules apply whether you're dealing with a class object or POD (int, char, etc.). You're declaring one object on line 37, and then (possibly) another on either line 69, 74 or 79. The fact that the name is the same doesn't change anything.

Think about what happens when you declare index variables in several while loops and name them all i. Where can you print the value of each of those is?

Actually it's a bad idea to shadow the name of the original object. You might consider creating the default object in an "else" block.

And you should be able to figure out where to do the printing.
Was This Post Helpful? 1
  • +
  • -

#6 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1837
  • View blog
  • Posts: 6,570
  • Joined: 19-February 09

Re: Using constructors

Posted 11 April 2017 - 09:02 PM

The constructor is a function that is called when the class instance is created, only one constructor is called. The default constructor was the name of the constructor supplied by the compiler when no other constructor was supplied, but came to mean any constructor with no parameters.
Was This Post Helpful? 1
  • +
  • -

#7 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 11 April 2017 - 09:11 PM

If I do the hanging else statement then it says:

circles.cpp: In function 'int main()':
circles.cpp:87:2: error: 'sphere' was not declared in this scope

and it doesn't compile.

At least I understand why it's going out of scope now- I thought I was calling the constructor like a function. Now where I read that it is implicitly called makes more sense.

But I still don't know what to do.

In the cp pasted code it would be line 82. The first time trying to use the object
Was This Post Helpful? 0
  • +
  • -

#8 r.stiltskin  Icon User is offline

  • Poorly Educated
  • member icon

Reputation: 1950
  • View blog
  • Posts: 5,215
  • Joined: 27-December 05

Re: Using constructors

Posted 11 April 2017 - 09:15 PM

To be precise, one constructor is being called on line 37 to instantiate your "default" circle. That object persists as long as the program is running.

If one of the if conditions applies, another constructor is being called to instantiate a second object but that object persists only inside its particular if block.

As to your "circles.cpp:87:2: error: 'sphere' was not declared in this scope" error, you probably wrote sphere rather than Circles sphere on line 87. (If not, please post the code that produces that error.)
Was This Post Helpful? 1
  • +
  • -

#9 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1837
  • View blog
  • Posts: 6,570
  • Joined: 19-February 09

Re: Using constructors

Posted 11 April 2017 - 09:20 PM

Each constructor has to initialize all the variables as only one is called, setters could be called.
Was This Post Helpful? 1
  • +
  • -

#10 jimblumberg  Icon User is online

  • member icon

Reputation: 5151
  • View blog
  • Posts: 16,111
  • Joined: 25-December 09

Re: Using constructors

Posted 11 April 2017 - 09:20 PM

Quote

etc, but then if one of the variables isn't initialized, I just get garbage. Isn't that the point of the default? That the private variables should be initialized?

No, the point of a "default" (no argument) constructor is to initialize the object when you define an object with no parameters. Every constructor should initialize all the class variables with either the supplied argument or with sensible default values. Also note that you can, when compiling with a C++11 or higher compatible compiler, call one of the other constructors. You also should start using constructor initialization lists instead of initializing the values in the body of the constructor.

Circles::Circles (float r) : Circles() // Call the default constructor to initialize the variables.
{
	cout << "circles y n was called with " << r << endl;
	radius = r;
}
// OR:
Circles::Circles (float r) : radius(r), center_x(0), center_y(0)   // Use constructor initialization list.
{
	cout << "circles y n was called with " << r << endl;
}



And as stated above all of your Circle instances in the if() statements will go out of scope at the end of the if() statements, so to show that something is being done you need to call the other functions inside the if() statement.


    if(rad == true && coor == true)
    {
        Circles sphere(size, x_coor, y_coor);
        sphere.printCircleStats();
        cout << "The area of the circle is " << sphere.findArea() << endl;
        cout << "The circumference of the circle is "
	     << sphere.findCircumference() << endl;
    }




Jim
Was This Post Helpful? 1
  • +
  • -

#11 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 11 April 2017 - 09:22 PM

The error is caused by

	sphere.printCircleStats(); 



I could paste the whole code again, but literally all I did was comment out Circles Sphere; at the top and added

	
	else
	{
		Circles sphere;
	}
	


Was This Post Helpful? 0
  • +
  • -

#12 r.stiltskin  Icon User is offline

  • Poorly Educated
  • member icon

Reputation: 1950
  • View blog
  • Posts: 5,215
  • Joined: 27-December 05

Re: Using constructors

Posted 11 April 2017 - 09:25 PM

So now all of your objects exist only inside the if statements.

As Jim said, you have to do the printing inside those if statements, not after they go out of scope.
Was This Post Helpful? 1
  • +
  • -

#13 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 11 April 2017 - 09:34 PM

OOHHHH duuuuhhhhhh Thannnkyou! Ugh I'm so tired. I've got it now. Thank you both of you!!
Was This Post Helpful? 0
  • +
  • -

#14 klg52486  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 85
  • Joined: 01-December 16

Re: Using constructors

Posted 12 April 2017 - 04:53 PM

Ok, so i fixed it, but could someone please tell me why my destructor seems to be called 5 times when as far as I can tell there are only 4 objects? The first object is destroyed before it moves on to the next one, but then it goes through 3 more, and then is called 4 times. I don't understand.

#include <iostream>
using namespace std;
//_________________________________________________________________________
// This program declares a class for a circle that will have 
// member functions that set the center, find the area, find
// the circumference and display these attributes.

//class declaration section   (header file)

class Circles    
{
public:
   void setCenter(int x, int y);
   double findArea();   
   double findCircumference(); 
   void printCircleStats(); // This outputs the radius and center of the circle. 
   
   Circles(float r, int x, int y)  // Constructor for user input. rad & coordinates
   {
	radius = r;
	center_x = x;
	center_y = y;
   }
   
   Circles(float r)   // Constructor for user input. radius only
   {
	radius = r;
	center_x = 0;
	center_y = 0;
   }
   
   Circles(int x, int y)  // Constructor for user input. coordinates only
   {
	radius = 1;
	center_x = x;
	center_y = y;
   }
   
   Circles()               // Default constructor
   {
    radius = 1;
   	center_x = 0;
	center_y = 0;
   }
   
   ~Circles() { cout << "This concludes the Circles class " << endl;}
private: 
   float  radius;
   int    center_x;
   int    center_y;
};      


const double PI = 3.14;

//Client section   

int main()
{
   char y_n; // user can enter y or n to specifying a value
   float  size; // user specified values for circle
	int	  x_coor,
		  y_coor;
   
   bool rad = false,
		coor = false;  // true if user enters data
	
	
	// Exercise 1
   Circles sphere(8);
   sphere.setCenter(9,10);
       
   cout << endl;
   cout << "The area of the first circle is " << sphere.findArea() << endl;
   cout << "The circumference of the circle is "
	    << sphere.findCircumference() << endl;
   sphere.printCircleStats();
	
	
	Circles sphere1; // default constructor for circle in exercise 2
	
	sphere1 = Circles(2); // sets radius to 2 as specified
	cout << endl;
	cout << "The area of the second circle is " << sphere1.findArea() << endl;
	cout << "The circumference of the circle is "
	     << sphere1.findCircumference() << endl;
	sphere1.printCircleStats();
	
	
	Circles sphere2; // default constructor for circle in exercise 2
		
	cout << endl;
	cout << "The area of the third circle is " << sphere2.findArea() << endl;
	cout << "The circumference of the circle is "
	     << sphere2.findCircumference() << endl;
	sphere2.printCircleStats(); 
	
	
	// Exercise 3- allows user to enter data and creates object sphere3
	// with correct parameters using if statement.
   cout << endl;
   cout << "This program finds the area and circumference " << endl
		<< "of a circle. Type y to enter a value for radius " << endl
		<< "or no to use the default radius of 1." 			<< endl;
	cin	>> y_n;
	
	if(y_n == 'y' || y_n == 'Y')
	{
		cout << endl
			 << "Enter the radius:   ";
		 cin >> size;
		rad = true; 
	}
	cout << endl
		 << "Type y to enter x and y coordinates for the " << endl
		 << "center of the circle or n to use the default " << endl
		 << "of (0,0)." << endl;
	 cin >> y_n;
	 
	 	if(y_n == 'y' || y_n == 'Y')
	{
		cout << endl
			 << "Enter the x and y coordinates (in the order)"
			 << "separated by a space:   ";
		 cin >> x_coor >> y_coor;
		 coor = true;		 
	}
   
	// user entered radius and coordinates
	if(rad == true && coor == true)
	{
		Circles sphere3(size, x_coor, y_coor);
		
		cout << endl;
		cout << "The area of the circle is " << sphere3.findArea() << endl;
		cout << "The circumference of the circle is "
			 << sphere3.findCircumference() << endl;
		sphere3.printCircleStats(); 
	} 
	// user entered radius 
	else if(rad == true && coor == false)
	{
		Circles sphere3(size);
		
		cout << endl;
		cout << "The area of the circle is " << sphere3.findArea() << endl;
		cout << "The circumference of the circle is "
			 << sphere3.findCircumference() << endl;
		sphere3.printCircleStats(); 
	} 
   	// user entered coordinates
	else if(rad == false && coor == true)
	{
		Circles sphere3(x_coor, y_coor);
		
		cout << endl;
		cout << "The area of the circle is " << sphere3.findArea() << endl;
		cout << "The circumference of the circle is "
			 << sphere3.findCircumference() << endl;
		sphere3.printCircleStats(); 
	} 	
	// user entered nothing
	else
	{
		Circles sphere3;  // default constructor for user circle
		
		cout << endl;
		cout << "The area of the circle is " << sphere3.findArea() << endl;
		cout << "The circumference of the circle is "
			 << sphere3.findCircumference() << endl;
		sphere3.printCircleStats(); 
	}	


   return 0;
}

//___________________________________________________________________________
//Implementation section     Member function implementation


// Fill in the code to implement the findArea member function
double Circles::findArea()
{
	return PI * radius * radius;
}

// Fill in the code to implement the findCircumference member function
double Circles::findCircumference()
{
	return 2 * PI * radius;
}


void Circles::printCircleStats()
// This procedure prints out the radius and center coordinates of the circle
// object that calls it.

{
   cout << "The radius of the circle is " << radius << endl;
   cout << "The center of the circle is (" << center_x 
        << "," << center_y << ")" << endl;
}

void Circles::setCenter(int x, int y)
// This procedure will take the coordinates of the center of the circle from 
// the user and place them in the appropriate member data.

{
   center_x = x;
   center_y = y;
} 


This post has been edited by klg52486: 12 April 2017 - 04:54 PM

Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 5502
  • View blog
  • Posts: 18,728
  • Joined: 05-May 12

Re: Using constructors

Posted 12 April 2017 - 05:51 PM

Did you also implement a copy constructor? If not, the compiler provided a default implementation if it needed it. Currently on a small screen phone so I've not had a chance to look closely at your code to see where a copy constructor would have been used.

Best I can see, line 82. I'll verify later when I'm on a proper screen.

Or better yet, what better time than now to learn how to use your debugger. Set a breakpoint on your destructor. Each time the breakpoint gets hit, look at the callstack to see which object instance is being deleted.
Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2