Variable doesn't update with Pointer

Hi,

I've created a code which calculates simple geometries of shapes, e.g. area, volume. A user is intended to feed in a number (in the main.cpp file). While the shapes have default sides, the member function file will determine if the user-provided number is greater than a minimum. If true, then the default side gets overwritten for whatever was user-provided.

At the beginning of the output, I print the default dimensions. At the end, I do the same, except it doesn't appear to work.

The example I'm trying here is the class Shapes member function set_rectangle(int L, int W).

When the program runs, it outputs the correct length. But when printing the default length afterwards, it doesn't appear to have changed.



What am I missing?

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/***** LIBRARIES AND HEADERS *****/
#include <iostream>

//using namespace std;
using std::cout;
using std::cin;
using std::endl;

#include "geometry_2.h"  // header file which contains class definition for Shapes class

int main()
{

    /* creates 4 objects "t0-t3" of class 'Shapes'
       The overload constructor provides the class Shapes with user-supplied parameters (where used, othewise default constructior parameters are used)

       When using default constructor arguements, at least 1 parameter has to be set
     */

    // declare objects, directly accessing individual class member functions
    Shapes t0;  // Shapes, default
    Shapes t1; // rectangle area
    Shapes t2; // box volume
    Shapes t3; // cylinder volume
              

    int side_1 = 12;
   // int *ptr_side_1 = NULL;
    //int *ptr_length = NULL;
    
    int side_2 = 4;
  //  int *ptr_side_2 = NULL;


    //ptr_side_1 = &side_1;
   // ptr_side_2 = &side_2;

    // pass parameters to class member functions (which are geometric figures)
    t0.get_dimensions();    // print default dimensions
    //t1.set_rectangle(2, 4);
    t1.set_rectangle(side_1, side_2);
    t2.set_box(7, 2, 4);
    t3.set_cylinder(1, 10);

    // print calculations:  area, volume
    t1.get_rectangle();
    t2.get_box();
    t3.get_cylinder();

    //When I uncomment this, and using addresses or pointers, the default values should now show they've been changed
    cout << endl;
    t0.get_dimensions();  // print default dimensions
    
    cout << "\n\n Press any key to close window...\n\n";
    // cin.get(); // keep terminal open until you press a key

    return 0;
}



header file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef GEOMETRY_2_H 
#define GEOMETRY_2_H


/*
Create a class which contains the Shape functions
The class memember functions are placed in 'public'
The class member variables are defined in private.
*/


class Shapes
{
public:

	Shapes(int = 1, int = 1, int = 1, int = 1);   // Shapes default constructor initializes class Shapes's private data members
	//~Shapes();  // destructor
	
	
	
	// set functions
	     //void set_dimensions(int, int, int, int);
	void set_rectangle(int,int);
	void set_box(int, int, int);
	void set_cylinder(int, int);

	// get functions
	void get_dimensions();  // default dimensions set by default constructor
    int get_rectangle();
	int get_box();
	double get_cylinder();	

private:

	int length;
	int width;
	int height;
	int radius;


};  // end class Shapes



#endif
#pragma once 


source file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
Class member function definitions for class Shape functions

*/

#include <iostream>

//using namespace std;
using std::cout;
using std::endl;

#include <iomanip>
#include "geometry_2.h"  // include deifinition of class Shapes from geometry_2.h

int minimum_length = 2;  // set min. length a dimension can be



/* Shapes constructor initializes class Shapes's private data members
The member functions then choose which of the  private data members to use
Thus, the constructor's purpose is just to set default values to the private data member,
but it's not required
*/
Shapes::Shapes(int L, int W, int H, int R)     
{
	length = L;
	width  = W;
	height = H;
	radius = R;
}  // end of Shapes constructor 


/***** Default Dimensions *****/
void Shapes::get_dimensions()  // print all default dimensions (later change into using setwidth, precision, etc. for string
{
	cout << "Dimensions (default): " << endl;
	cout << "  length = " << length << endl;    // print length
	cout << "  width = " << width << endl;     // print width
	cout << "  height = " << height << endl;   // print height
	cout << "  radius = " << radius << endl;   // print height
	cout << "" << endl;  //skip a space
}

/***** Set Functions *****/
// using parameters: length and width
void Shapes::set_rectangle(int L, int W)
{
	/*
	length = (L >= 3) ? L : 0; // this style asks a T/F question:  If the condition is true, then set provided length to L.  Else, set it to 0
	                              However, if you also want to print a statement, or do multiple things if condition is false, use if / else statement
	*/

	if (L >= minimum_length)
	{
		cout << "\nL = " << L << endl;
		cout << "default length = " << length << endl;
		int *ptr_length = NULL;
		ptr_length = &length;
		*ptr_length = L; // set to provided parameter
		length = *ptr_length;
		cout << "new length = " << length << endl;
	}

		else
		{
			length = 0;
			cout << "length = " << length << endl;
			cout << "   ***invalid Rectangle dimensions!  length must be > " << minimum_length << endl;
		}

	width = (W >= 3) ? W : 0;

}

// using parameters: length, width, height 
void Shapes::set_box(int L, int W, int H)
{
	length = (L >= minimum_length) ? L : 0; 
	width  = (W >= minimum_length) ? W : 0;
	height = (H >= minimum_length) ? H : 0;

}
// using parameters: height, radius
void Shapes::set_cylinder(int H, int R)
{
	length = (H >= minimum_length)  ? H : 0;
	width  = (R	>= minimum_length)  ? R : 0;
}


/***** Get Functions *****/
int Shapes::get_rectangle()
{	int a = length * width;
    cout << "rectangle area = " << a << endl;
	return a;
}

int Shapes::get_box()
{
	int a = length * width * height;
	cout << "box volume = " << a << endl;
	return a;
}

double Shapes::get_cylinder()
{
	double a = 2 * radius * 3.141592654 * height;  // later insert "pi", prob using math lib.  Double is preferred over float due to rounding issues w/float
	cout << "cylinder volume = " << cout.precision(3) << a << endl;
	                                /*
									  Outputs decimal position n - 1 for following var.  
										  examples:
										  If using (3), you'll get 2 decimal places
										  If using (1), you'll get 0 decimals, only the integer
									*/
	return a;  
}


Last edited on
But when printing the default length afterwards, it doesn't appear to have changed.

In your main function, you create your t0 object, but you only ever call t0.get_dimensions(); on it.
Your t0 object is not being changed.

btw, this is unnecessarily convoluted:
1
2
3
4
int *ptr_length = NULL;
ptr_length = &length;
*ptr_length = L;
length = *ptr_length;


This is can be simplified to:
1
2
3
int *ptr_length = &length;
*ptr_length = L;
length = *ptr_length;


which can then be simplified to:
1
2
*(&length) = L;
length = *(&length); // no-op 


which can then be simplified to:
length = L;
Last edited on
As 1 file for easy compilation, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <iomanip>
using namespace std;

class Shapes
{
public:
	Shapes(int = 1, int = 1, int = 1, int = 1);

	void set_box(int, int, int);
	void set_cylinder(int, int);
	void set_rectangle(int, int);
	void set_circle(int);

	// get functions
	void get_dimensions() const;  // default dimensions set by default constructor
	int get_rectangle() const;
	int get_box() const;
	double get_cylinder() const;

private:
	int length {1};
	int width {1};
	int height {1};
	int radius {1};
};

const int minimum_length = 2;  // set min. length a dimension can be

Shapes::Shapes(int L, int W, int H, int R) : length(L), width(W), height(H), radius(R) {}

void Shapes::get_dimensions() const
{
	cout << "Dimensions: " << endl;
	cout << "  length = " << length << endl;    // print length
	cout << "  width = " << width << endl;     // print width
	cout << "  height = " << height << endl;   // print height
	cout << "  radius = " << radius << endl;   // print height
	cout << endl;  //skip a space
}

void Shapes::set_rectangle(int L, int W)
{
	if (L >= minimum_length) {
		cout << "default length = " << length << endl;
		length = L;
		cout << "new length = " << length << endl;
	} else {
		length = 0;
		//cout << "length = " << length << endl;
		cout << "   ***invalid Rectangle dimensions!  length must be > " << minimum_length << endl;
	}

	width = (W >= 3) ? W : 0;
}

// using parameters: length, width, height
void Shapes::set_box(int L, int W, int H)
{
	length = (L >= minimum_length) ? L : 0;
	width = (W >= minimum_length) ? W : 0;
	height = (H >= minimum_length) ? H : 0;

}
// using parameters: height, radius
void Shapes::set_cylinder(int H, int R)
{
	height = (H >= minimum_length) ? H : 0;
	radius = (R >= minimum_length) ? R : 0;
}

/***** Get Functions *****/
int Shapes::get_rectangle() const
{
	const int a = length * width;

	cout << "rectangle area = " << a << endl;
	return a;
}

int Shapes::get_box() const
{
	const int a = length * width * height;

	cout << "box volume = " << a << endl;
	return a;
}

double Shapes::get_cylinder() const
{
	const double a = 2.0 * radius * 3.141592654 * height;

	cout << "cylinder volume = " << fixed << setprecision(3) << a << endl;
	return a;
}

int main()
{
	Shapes t0;  // Shapes, default
	Shapes t1; // rectangle area
	Shapes t2; // box volume
	Shapes t3; // cylinder volume

	t0.get_dimensions();
	t1.set_rectangle(12, 4);
	t2.set_box(7, 2, 4);
	t3.set_cylinder(2, 10);

	t1.get_rectangle();
	t2.get_box();
	t3.get_cylinder();

	cout << endl;
	t0.get_dimensions();
	t1.get_dimensions();
	t2.get_dimensions();
	t3.get_dimensions();
}



Dimensions:
  length = 1
  width = 1
  height = 1
  radius = 1

default length = 1
new length = 12
rectangle area = 48
box volume = 56
cylinder volume = 125.664

Dimensions:
  length = 1
  width = 1
  height = 1
  radius = 1

Dimensions:
  length = 12
  width = 4
  height = 1
  radius = 1

Dimensions:
  length = 7
  width = 2
  height = 4
  radius = 1

Dimensions:
  length = 1
  width = 1
  height = 2
  radius = 10

Ganado, thank you for pointing all this out. Always good to simplify!

seeplus. very interesting what you did in line 30 of your response. Much cleaner. I'm curious now about why your using const. Examples,

1
2
3
4
5
6
7
8
/***** Get Functions *****/
int Shapes::get_rectangle() const
{
	const int a = length * width;

	cout << "rectangle area = " << a << endl;
	return a;
}



Also, why are you using multiple objects for get_dimensions? Perhaps I'm new at it, but is it because each object can only be assigned to 1 member function?

1
2
3
4
t0.get_dimensions();
t1.get_dimensions();
t2.get_dimensions();
t3.get_dimensions();


For example, since I used the object t2 for box, is it true then that I can only use t2 again for something "box-related"? (not sure else how to ask that question.)


I'm curious now about why your using const.
Const correctness is both a promise and sanity control.

Does get_rectangle() change the Shapes object? No. It merely reads length and width.

When we declare the member function const, int Shapes::get_rectangle() const
we
1) Tell the user that this function can be called on const object:
1
2
const Shapes abc;
abc.get_rectangle(); // ok, if get_rectangle is const 


2) Make the compiler shout "error", if we accidentally try to modify the object within the function


Operating with const objects not only can reveal/prevent logical errors, but might allow the compiler to optimize a bit more.
Topic archived. No new replies allowed.