How to make class with const properties assignable? - c++

I have a simple point class:
class Point {
public:
Point(const double, const double);
/** This constructor creates invalid point instance **/
Point();
~Point();
const double x;
const double y;
/** This returns true if one of the values is NaN **/
bool isInvalid() const;
/** Returns true if coordinates are equal **/
bool equal(const Point& p) const;
};
Values x and y are const so that I can be sure they never change. They are supposed to be always constant. The problem is I can't assign to variables holding Point:
Point somePoint;
... meanwhile, things happen ...
//ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
somePoint = Point(x, y);
I understand that assigning is a problem because somePoint.x = something is forbidden. I need to use point to hold last point value during rendering:
Point lastPoint;
PointInGraph* point = graphValues.last;
while((point = point->next())!=nullptr) {
// calculate pixel positions for point
double x,y;
...
if(!lastPoint.isInvalid())
drawer.drawLine(round(lastPoint.x), round(lastPoint.y), round(x), round(y));
// ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
lastPoint = Point(x, y);
}
So does const in class properties simply make any variable of that class type const as well? Or is there a workaround?

It's not possible. It would require modifying const values.
Instead of making x and y themselves const, make them non-const but provide a const interface to them, i.e. by making them private and providing const getters.

Instead of making the variables const you could just not provide any way for the user to change the values by:
making them private
only allowing assignment to a another instance as the only way to change the values.
You can see how this would work in the following example:
#include <iostream>
class Point {
public:
Point(const double x_ = 0, const double y_ = 0) : x(x_), y(y_) {}
double getX() const { return x; }
double getY() const { return y; }
private:
double x;
double y;
};
int main()
{
Point a{1,5};
Point p;
p = a;
std::cout << p.getX() << ", " << p.getY(); // no error here
//p.x = 5; // error here now
//p.y = 7; // error here now
}
Live Example
If you un-comment the last two lines you will get an error to prove that you cannot change x and y.

Actually it's, of course, possible by directly technique called cast away constness which is a known loophole in const mechanic in C++. Basically I can abuse the fact that const int* can be assigned to int* variable. The possible solution:
Point& Point::operator=(const Point& p)
{
*((double*)&x)=p.x;
*((double*)&y)=p.y;
}
This is of course not recommended, but I'm not the one of the people who think that knowledge is dangerous.

Related

C++ What is the point of using const in a class setter function?

I am going through a text book to freshen up my (fairly bad) C++ knowledge and I came across this code example (shortened):
class MyClass{
private:
int count;
double price;
string name;
public:
void setValues(const int&, const double&, const string&);
};
void MyClass::setValues(const int& c, const double& p, const string& n){
count = c;
price = p;
name= n;
}
int main(){
myClass pOne;
pOne.setValues(5, 0.75, "Kiwi");
return 0;
}
The Way I understand the const keyword and the way it was described in the book thus far is that I can use it to declare constants, which should not be subject to change. This is better for the compiler since it knows that the values won't change.
But here I use const every time I set values
void MyClass::setValues(const int& a, const double& p, const string& b)
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
This is flawed logic. Consider this small example:
const int x = 42;
int y = x;
The value of x is assigned to y. Just because x is constant does not imply that y is too. You can change the value of y afterwards.
In the function signature the const means the usual: You cannot modify the parameters. It would be odd if a setter would change them.
struct foo {
int value = 42;
void set(int& x) {
value = x;
x = 42; // what ?!?
}
};
int main() {
int a = 2;
foo f;
f.set(x);
std::cout << x; // prints 42.... what?!?
const int b = 3;
f.set(b); // error because b is const :(
}
The setter takes its parameters by constant references because it tries to avoid a copy (hence reference) and parameters are not modified by the call (hence const).
Passing int as const int& however, is not really recommended, because it isn't cheaper than passing the int by value.

C++ should I use pointer or reference?

I would like to have an insight about whenever I should be using references or pointers.
Let's take the example of a Polygon class using a Rectangle class for its internal bounding box.
Polygon.h
class Polygon {
private:
std::list<Point> _points;
Rectangle _boundingBox;
public:
Polygon(const std::list<Point> &);
public:
const std::list<Point> &getPoints() const;
const Rectangle &getBoundingBox() const;
private:
void setBoundingBox();
};
Polygon.cpp
#include <iostream>
#include "Polygon.h"
Polygon::Polygon(const std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1) {
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
}
if (points.front() != points.back()) {
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
}
std::list<Point>::const_iterator it;
for (it = ++points.begin(); it != points.end(); ++it) {
this->_points.push_back(*it);
}
this->setBoundingBox();
}
void Polygon::translate(const std::array<float, 2> &vector)
{
std::list<Point>::iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it) {
(*it).setX((*it).getX() + vector[0]);
(*it).setY((*it).getY() + vector[1]);
}
Point topLeft = this->_boundingBox->getTopLeft();
Point bottomRight = this->_boundingBox->getBottomRight();
topLeft.setX(topLeft.getX() + vector[0]);
topLeft.setY(topLeft.getY() + vector[1]);
bottomRight.setX(bottomRight.getX() + vector[0]);
bottomRight.setY(bottomRight.getY() + vector[1]);
}
const std::list<Point> &Polygon::getPoints() const
{
return this->_points;
}
const Rectangle &Polygon::getBoundingBox() const
{
return this->_boundingBox;
}
void Polygon::setBoundingBox()
{
float xMin = this->_points.front().getX();
float xMax = this->_points.front().getX();
float yMin = this->_points.front().getY();
float yMax = this->_points.front().getY();
std::list<Point>::const_iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it)
{
Point point = *it;
if (point.getX() < xMin) {
xMin = point.getX();
}
if (point.getX() > xMax) {
xMax = point.getX();
}
if (point.getY() < yMin) {
yMin = point.getY();
}
if (point.getY() > yMax) {
yMax = point.getY();
}
}
this->_boundingBox = new Rectangle(Point(xMin, yMin), Point(xMax, yMax));
}
std::ostream &operator<<(std::ostream &out, const Polygon &polygon)
{
std::list<Point>::const_iterator it;
for (it = polygon.getPoints().begin(); it != polygon.getPoints().end(); ++it) {
out << (*it);
if (it != polygon.getPoints().end()) {
out << " ";
}
}
return out;
}
Rectangle.h
#pragma once
#include <stdexcept>
#include "Point.h"
class Rectangle {
private:
Point _topLeft;
Point _bottomRight;
public:
Rectangle(const Point &, const Point &);
public:
const Point &getTopLeft() const;
const Point &getBottomRight() const;
float getWidth() const;
float getHeight() const;
};
Rectangle.cpp
#include "Rectangle.h"
Rectangle::Rectangle(const Point &topLeft, const Point &bottomRight)
{
if (topLeft.getX() > bottomRight.getX() || topLeft.getY() > bottomRight.getY()) {
throw std::invalid_argument("You must specify valid top-left/bottom-right points");
}
this->_topLeft = topLeft;
this->_bottomRight = bottomRight;
}
const Point &Rectangle::getTopLeft() const
{
return this->_topLeft;
}
const Point &Rectangle::getBottomRight() const
{
return this->_bottomRight;
}
float Rectangle::getWidth() const
{
return this->_bottomRight.getX() - this->_topLeft.getX();
}
float Rectangle::getHeight() const
{
return this->_bottomRight.getY() - this->_topLeft.getY();
}
Point.h
#pragma once
#include <ostream>
#include <cmath>
class Point {
private:
float _x;
float _y;
public:
Point(float = 0, float = 0);
public:
float distance(const Point &);
public:
float getX() const;
float getY() const;
void setX(float);
void setY(float);
};
std::ostream &operator<<(std::ostream &, const Point &);
bool operator==(const Point &, const Point &);
bool operator!=(const Point &, const Point &);
Point.cpp
#include "Point.h"
Point::Point(float x, float y)
{
this->_x = x;
this->_y = y;
}
float Point::distance(const Point &other)
{
return std::sqrt(std::pow(this->_x - other.getX(), 2) + std::pow(this->_y - other.getY(), 2));
}
float Point::getX() const
{
return this->_x;
}
float Point::getY() const
{
return this->_y;
}
void Point::setX(float x)
{
this->_x = x;
}
void Point::setY(float y)
{
this->_y = y;
}
std::ostream &operator<<(std::ostream &out, const Point &point)
{
out << "(" << point.getX() << ", " << point.getY() << ")";
return out;
}
bool operator==(const Point &p1, const Point &p2)
{
return p1.getX() == p2.getX() && p1.getY() == p2.getY();
}
bool operator!=(const Point &p1, const Point &p2)
{
return p1.getX() != p2.getX() || p1.getY() != p2.getY();
}
A lot of questions come with this snippet of code.
This does not compile because obviously whenever we try to create a Polygon, it ends up trying to create a Rectangle with a default constructor which does not exist.
I can't use initializer list because obviously the bounding box depends on some computed values from my list of points.
I could create a default constructor creating two Point(0, 0) by default for the Rectangle but this does not make much sense.
I could use pointers but then I feel this is not the nicest solution as I tend to think this is mostly used for polymorphism in C++ we should prefer reference whenever possible.
How should I then proceed ?
I feel I am missing something out about C++ and could learn a lot from this.
I think your main question is about how to deal with the problem of needing to initialize both std::list<Point> _points; and Rectangle _boundingBox;, while also doing some validation of _points.
The simplest solution is to just give Rectangle a default constructor (or pass two default Points as initializer). Then once you have validated the points argument in the constructor, you calculate the Rectangle based on the points.
A slightly more complicated alternative is to allow the validation function to be invoked from the ctor-initializer list, e.g.:
Polygon::Polygon(std::list<Point> points)
: _points( validate_point_list(points), std::move(points) ), _boundingBox( calculateBoundingBox(_points) )
{
}
where you have functions (which could be free functions):
void validate_point_list(std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1)
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
if (points.front() != points.back())
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
// caller must pass in same first and last point, but we only store one of the two
points.erase( points.begin() );
}
and
Rectangle calculateBoundingBox(std::list<Point> const &_points)
{
// whatever logic you have in setBoundingBox, except return the answer
}
Note that the loop in your Polygon constructor is unnecessarily complicated. You could have just written _points = points; and then erased the extra point (which is O(1) for lists).
Note that I have passed by value and then used std::move. The reason is that if the argument given is a rvalue then it can just be moved right on through into where it's being stored; whereas with the const & version, a copy is stored and then the original is destructed.
I would use const & a lot less than you did. Small objects , such as Point and Rectangle, don't suffer a performance penalty from pass-by-value (and might even be more efficient that way). And as mentioned in the previous paragraph; if your function accepts a parameter and it is going to take a copy of that parameter, it's better to pass by value .
Passing by reference is best only when you are using but not storing the values passed. For example, calculateBoundingBox.
Finally, once you get this working, you might want to think about having the Polygon constructor accept an iterator pair of points range, and/or a std::initializer_list.
I would defined a default constructor for Rectangle class as private and I would make Polygon class a friend of Rectangle class:
class Rectangle {
friend class Polygon;
Point _topLeft;
Point _bottomRight;
Rectangle(); // accessible only to friends
public:
Rectangle(Point const&, Point const&);
...
};
And then in setBoundingBox():
void Polygon::setBoundingBox() {
...
_boundingBox._topLeft = Point(xMin, yMin);
_boundingBox._bottomRight = Point(xMax, yMax);
}
Thus, I wouldn't expose the default constructor of Rectangle and at the same time I would have a concrete object which is more efficient in terms of cache performance.
I feel as though you should have a separate class called BoundingBox that
1) Takes a collection of points in its constructor
2) Is inherited from Rectangle
Meanwhile, Rectangle should have a state, along the lines of NOT_A_RECTANGLE or it could throw an exception. Just be sure you clean up when throwing exceptions from a constructor.
Then you would construct the bounding box as part of the construction of the polygon and you can verify that a bounding box is possible as part of your error checking. (probably rather than 3 sides check, but I am no geometry expert)
BoundingBox would remain a member of Polygon.
This would be more RTTI.
It occurs to me though, that if you translate or rotate the polygon, you've also go to translate or rotate the bounding box. You might want to consider making the list of points its own object and sharing them. This would be a more advanced topic. You can for now get away with just recalculating the bounding box on operations performed upon the polygon.
As to whether to use a reference, a pointer, or pass by value, I don't know that there is a black and white list of things to consider for this, but a few are:
Is the object large enough to even worry about it? A rectangle is 4 floats?
Are there interfaces or base classes you will need to cast to, rather than always using the class itself? If so, you've got no choice but to use a pointer of some sort. The pointer could be unique, shared, weak, etc. depending on the situation. You have to ask yourself who owns it, whats the life time, and are there circular references?
Most people will probably use a reference whenever possible rather than a pointer, but only when passing by value doesn't qualify.
IMO, since you are just "GetBoundingBox", I think it would be simple and more maintainable to just return a copy of the bounding box by value rather than some const reference and definitely more than a pointer.
One solution would be to write a programmatic constructor for Rectangle that takes as its argument a const std::list<Point>&. It could traverse the list once, computing the maximum and minimum x and y. Then, your Polygon constructor would become:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox(points)
{
// ...
}
An alternative is to move the code to find the bounding box from a list of points to a helper function, then define a move constructor Rectangle::Rectangle( Rectangle&& x ). In that case, your Polygon constructor would be:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox( findBoundingBox(points) )
{
// ...
}
Either way, you could update a bounding box with assignment, so you might want an assignment operator like Rectangle& Rectangle::operator= ( Rectangle&& x ) to make that more efficient. You can skip the Rectangle&& versions if a Rectangle is just Plain Old Data. But if you do this a lot, you might overload Rectangle& findBoundingBox( const std::list<Point>& src, Rectangle& dest ) to update in place with no copying.
On a minor side note, I’d discourage you from using identifiers that begin with underscores, since those names are reserved in the global namespace in C++, and your libraries might declare something named _point.

How to create copy constructor in C++/CX with class having properties

I'm new to C++/CX. I want to create a Vector class with two properties X and Y.
In standard C++, the copy constructor is:
Vector(const Vector& v);
I translate that to C++/CX as:
Vector(const Vector^ v);
Here's the class:
Header:
ref class Vector
{
public:
Vector();
Vector(const Vector^ v);
property double X;
property double Y;
};
Implementation:
Vector::Vector()
{
X = 0;
Y = 0;
}
Vector::Vector(const Vector^ v)
{
this->X = v->X;
this->Y = v->Y;
}
But I got an error when assigning v->X to this->X as: no instance of function "Vector::X::get" matches the argument list and object (the object as type qualifiers that prevent a match).
How to implement the copy constructor correctly?
Thanks.
Your problem is not directly related to copy-constructors. When I compile your code, I get the following error:
'Vector::X::get' : cannot convert 'this' pointer from 'const Vector' to 'Vector %'
This shows that the problem is with const-ness, see for example this question and its accepted answer.
It seems like the problem is that for trivial properties, the get accessor is not declared const. Because of that, you can't access the property on a const Vector^.
I think a solution would be not to use trivial properties, but implement both accessors yourself, making the get accessor const:
private:
double x;
double y;
public:
property double X
{
double get() const { return x; }
void set(double value) { x = value; }
}
property double Y
{
double get() const { return y; }
void set(double value) { y = value; }
}
The problem with this approach is that you can't have const methods in WinRT types (which, I assume, is why get accessors are not const in trivial properties). So, if you changed your type to public ref class, you would get this error:
'get': 'const' and 'volatile' qualifiers on member functions of WinRT types are not supported
Because of that, I think your best option is to not use const in your copy constructor:
Vector::Vector(Vector^ v)
{
this->X = v->X;
this->Y = v->Y;
}
Although I'm not sure why would you even need a copy constructor for ref class, since you always use it as a reference.

Programming style: object with passages by references or value? (c++)

This is a general question on programming style. Let's say I have an object Line which has some methods and private variables Point point_a_ and Point point_b_. Let's say that at some point I need to change the position of the two points. What programming style would you prefer between the following cases? They all do the same thing (or should do: I didn't compile, but seems pretty straightforward).
CASE 1
Class Line {
public:
Line(Point point_a, Point point_b) : point_a_(point_a), point_b_(point_b) {}
void UpdatePoints(Point point_a, Point point_b) {
point_a_ = point_a; point_b_ = point_b;
}
double Distance();
private:
Point point_a_;
Point point_b_;
};
int main (int argc, char * const argv[]) {
Point point_a(0,0,0);
Point point_b(1,1,1);
Line line(point_a,point_b);
std::cout<<line.Distance()<<"\n";
point_a.x = 1;
line.UpdatePoints(point_a,point_b);
std::cout<<line.Distance()<<"\n";
}
CASE 2
Class Line {
public:
Line(Point point_a, Point point_b) : point_a_(point_a), point_b_(point_b) {}
Point& point_a() { return point_a_; }
Point& point_b() { return point_b_; }
double Distance();
private:
Point point_a_;
Point point_b_;
};
int main (int argc, char * const argv[]) {
Point point_a(0,0,0);
Point point_b(1,1,1);
Line line(point_a,point_b);
std::cout<<line.Distance()<<"\n";
line.point_a().x = 1;
std::cout<<line.Distance()<<"\n";
}
CASE 3
Class Line {
public:
Line(Point* point_a, Point* point_b) : point_a_(point_a), point_b_(point_b) {}
double Distance();
private:
Point* point_a_;
Point* point_b_;
};
int main (int argc, char * const argv[]) {
Point point_a(0,0,0);
Point point_b(1,1,1);
Line line(&point_a,&point_b);
std::cout<<line.Distance()<<"\n";
point_a.x = 1;
std::cout<<line.Distance()<<"\n";
}
Any feedback is greatly appreciated!!
Thanks!
[EDIT] Speed is paramount in my software!
In this simple scenario I might just use public member variables.
Otherwise I would provide getters that return a const reference and matching setters.
class Line {
public:
Line(const Point& p1, const Point&p2) : m_p1(p1), m_p2(p2) {}
const Point& p1() const
{ return m_p1; }
const Point& p2() const
{ return m_p2; }
void setP1(const Point& p1)
{ m_p1 = p1; }
void setP2(const Point& p2)
{ m_p2 = p2; }
private:
Point m_p1;
Point m_p2;
};
Case three is totally out because it completely violates principles of encapsulation. Case two does as well, to a slightly lesser extent. I would prefer option one, but did you consider possibly making the points immutable and forcing you to create a new object when it changes?
Also to be pedantic if I remember correctly from many years ago, a line technically extends infinitely in both directions. You're actually representing a line segment.
Case 2 is no better than public member variables. In particular, it doesn't encapsulate anything.
Case 3 makes ownership of the points unclear. Consider what happens if your points are local variables in the calling function, and then they go out of scope. It also offers no benefits over public member variables.
So out of these three options, Case 1 is the cleanest, IMO. Other options are:
simply use public member variables.
make Line immutable.
use set and get functions.
I would choose either case 1 or an immutable Line class.
Case 2 allows changes to the Point objects without the knowledge of their containing line. At some point, you might need the line to know if its points have been changed.
Case 3 either makes the Line object dependent on the lifetime of the Points, or makes the Line the owner of the points, which is not clear from the API.
An immutable Line would allow you to create a new Line object with new points.
Case 4 -- Prefer passing by const reference rather than value (or pointer):
class Line
{
public:
Line(const Point& a, const Point& b) : a_(a), b_(b)
{}
const Point& get_a() const { return a_; }
const Point& get_b() const { return b_; }
void set_a(const Point& a) { a_ = a; }
void set_b(const Point& b) { b_ = b; }
private:
Point a_;
Point b_
};
This is better in that in enforces encapsulation - the only way to change the variables held in the class after construction is a specific mutator method.
The accessors return a const reference, so they cannot be modified (copies made from these can be).
The class as a whole is made const-correct.
References are arguably better than pointers in this instance because they are guaranteed (unless you specifically break that guarantee) to not be NULL.
Consider another option:
class Segment {
public:
Segment(Point point_a, Point point_b);
Point point_a() const;
Point point_b() const;
private:
Point point_a_;
Point point_b_;
};
double Distance( Segment seg );
int main (int argc, char * const argv[]) {
Point point_a(0, 0, 0);
Point point_b(1, 1 ,1);
Segment seg(point_a, point_b);
std::cout << Distance(seg) << "\n";
point_a.x = 1;
seg = Segment(point_a, point_b); // reset
std::cout << Distance(seg) << "\n";
}
I used the name Segment as per suggestion above. This style is closer to functional programming style. Segment is immutable unless you explicitly reset it with a common assignment syntax. Distance is not a member function because it can be implemented in terms of Segment's public interface.
Regards,
&rzej

Return reference to sliced object (supertype)

Consider the following classes:
class Coord
{
public:
double _x, _y;
Coord(double x, double y)
{
_x = x;
_y = y;
}
};
class NamedPoint : public Coord
{
public:
int _id;
NamedPoint(int id, double x, double y) :
Coord(x,y),
_id(id)
{
}
};
I'd like to create a member function of NamedPoint -- coord() -- that returns a reference of type Coord corresponding to the NamedPoint.
For example, I'd like to something like:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
But I get a warning about temporary variables and I'm not crazy about it.
Of course, the following works:
Coord coord()
{
Coord c = *this;
return c;
}
But I'd rather return a reference.
Does anyone know if this is possible using inherited classes?
Sorry for not explaining the point of the function. I'm overloading the == operator differently for Coord and NamedPoint. Coord would simply check {x,y} and NamedPoint would check {id,x,y}. If I forget to cast a NamedPoint to a Coord before this == test, I'll use the wrong version.
So, while I realize that
(Coord)np1 == (Coord)np2
would give me what I want, I'd rather use something like
np1.coord() == np2.coord()
which I think is more clear as to what is going on.
What's the point of the function? NamedPoint is implicitly convertible to Coord anyway:
void foo(Coord& c)
{
c._x = 5;
}
NamedCoord nc(0, 1, 2);
foo(nc); // c references the Coord part of nc
Anyway, your function should simply use this conversion:
const Coord& NamedPoint::coord()
{
// Bad: takes the value of *this and slices off
// the derived bits, leaving a temporary Coord.
/* return ((Coord)*this); */
// Good: takes the value of *this and refers
// to the base bits, no temporaries.
return *this;
// (Same as:)
/* return ((Coord&)*this); */
}
#GMan gives the main solution.
However, it might be interesting to note in more detail the problem:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
This is much the same as:
const Coord& NamedPoint::coord()
{
Coord c = *this;
return c;
}
Here it is clear that you are returning a reference to a temporary on the stack, which makes the reference to it useless, and hence the warning.
Now in the case presented, Coord is the base class and hence we have the simple solution given by #Gman.
In the general case, the principle is that if you want a reference to something, you better make sure that something will still be around.