3.1 Methods in class Point and class Rectangle
In this exercise we will add methods to class Point and Rectangle from the enclosing slide.
First, however, we notice that a rectangle contains its two points. In a similar Java or C# program (programmed with classes) the rectangle would have references (in the meaning of C++ pointers) to two points.
Add a couple of methods that access the x and y coordinates of a point. This is very easy. Do you miss C#-like properties in C++?
Next, write two methods that access the two corner points of a rectangle. Do you want to return copies of the points? Pointers to the points? Or references to the points? Please play with each of these possiblities, and discuss pros and cons.
Add an area method to Rectangle. This method will most likely need to access to the x and y coordinates of the corner points of the rectangle.
Add move methods to both class Point and Rectangle. The methods should implement relative displacement of points and rectangles.
In Rectangle::move, are you able to establish (C++) references to its two corner points, such that moving the two points also will also move the rectangle?
If you get too frustrated by dealing with Point& you may consider a version that works on Point*...
Finally, supply output functions for Point and Rectangle objects, by overloading operator<< for these two classes.
3.2 Use of constructors with object on the free store
Rewrite the program shown above such that all Point objects are constructed in the free store (on the heap). The dynamically allocated points should have the same (x,y) coordinates as the points in the program shown above.
This involves use of pointer and dynamic allocation, instead of automatic variables of class type and 'static allocation'.
The version of the program produced in this exercise is - in some respect - similar to a Java or C# version of the program. Discuss!
Consider how to initialize the array ap, which in this version of the program should be an array of Point pointers.
3.3 Point destruction - now with a problematic point copy constructor
We continue our work with class Point, using a dynamically allocated point representation. It may be beneficial to review the two version of the classes (together with client programs) on the accompanying slide.
In the verison below we add a copy constructor to class Point. This constructor turns out to be problematic.
// Redoing the example - same header file as the previous version. class Point { private: double *point_representation; public: Point(); Point(double, double); Point(Point&); // A new copy constructor ~Point(); // Destructor double getx () const; double gety () const; void move(double dx, double dy); }; std::ostream& operator<<(std::ostream&, const Point&);
The class is implemented as follows:
#include <cmath> #include <iostream> #include "point.h" Point::Point(){ point_representation = new double[2]; point_representation[0] = 0.0; point_representation[1] = 0.0; } Point::Point(double x_coord, double y_coord){ point_representation = new double[2]; point_representation[0] = x_coord; point_representation[1] = y_coord; } Point::Point(Point& p): point_representation(p.point_representation){ // ATTEMPTING copy construction. } Point::~Point(){ std::cout << "Deleting point" << "(" << getx() << "," << gety() << ")" << std::endl; delete[] point_representation; } double Point::getx () const{ return point_representation[0]; } double Point::gety () const{ return point_representation[1]; } void Point::move(double dx, double dy){ point_representation[0] += dx; point_representation[1] += dy; } std::ostream& operator<<(std::ostream& s, const Point& p){ return s << "(" << p.getx() << "," << p.gety() << ")" ; }
There are problems in the following program: (1) When point r is moved, s is also moved. This is not as intended. In addition, the program aborts on exit from the function f.
#include <iostream> #include "point.h" using namespace std; int f(){ Point p, q, r(11.0, 12.0); cout << "Point p: " << p << endl; // (0,0) cout << "Point q: " << q << endl; // (0,0) cout << "Point r: " << r << endl; // (11,12) Point s(r); // s is intended to be a copy of r. cout << "Point s: " << s << endl << endl; // (11,12) r.move(1.0, 2.0); // Moves r. cout << "Point s: " << s << endl; // (12,14) !! s is ALSO MOVED - why? cout << "Point r: " << r << endl << endl; // (12,14) // PROGRAM ABORTS ON EXIT FROM F - why? } int main(){ f(); }
Explain both of the problems, and make a correct version of class Point.
3.4 Conversion via constructors
In the program shown above, a Point can be converted to a Tripple via a constructor Tripple(Point). The other way around, we convert a Tripple to a Point with use of a conversion operator in class Tripple
In this exercise we want to provide for a more symmetric solution. We keep the constructor Tripple(Point). Your task is to program the symmetric constructor Point(Tripple). Your starting point is the header file and the cpp file
You may enconter a couple of minor challenges when you rewrite the program. First, class Tripple must now be declared (it must be known by the compiler) in order to compile class Point. The reason is that class Point now uses the name Tripple (in the new constructor).
As another challenge, the new constructor Point(Tripple) in class Point needs access to the three encapsulated, private data members in class Tripple. Consider setting up appropriate friendship, or program accessor member functions.
With this in place, rerun the program from above. Do you get the expected results (without surprises)?
3.5 Discuss encapsulation, visibility and access
Generated: Tuesday March 26, 2013, 13:03:32