Having trouble with overloading operator<. I am trying to overload the operator< so that I can sort my Line2D object based on pt1's x. But I am having trouble figuring out how to declare the function.
I am getting the error:
object has type qualifiers that are not compatible with the member function "Point2D::getX".
What I have tried: removing const, putting Point2D &l2dobj instead.
class Line2D
{
private:
Point2D pt1;
Point2D pt2;
public:
bool operator<( const Line2D &l2dobj)
{
return (pt1.getX() < l2dobj.pt1.getX());
}
}
class Point2D
{
protected:
int x;
int y;
public:
int getX();
int getY();
}
Point2D::getX doesn't accept const instance, you cannot apply it on l2dobj while it is a const reference, change getX (and a priori getY) to :
class Point2D
{
protected:
int x;
int y;
public:
int getX() const;
int getY() const;
};
As a general way declare the methods const the more you can, and same for their parameters
Related
I have the following classes:
class Point
{
private:
Vector2d _coordinates;
int _label;
public:
Point(const double x = 0.0, const double y = 0.0);
Point(Vector2d coordinates);
void setCoordinates(const double x, const double y) {_coordinates(x, y);}
const Vector2d& getCoordinates() const {return _coordinates;}
int getPointLabel() const{ return _label;}
void setPointLabel(int label);
class PolygonCutter
{
//output parameters
vector<Point> _newPoints;
vector< vector<Point>> _cuttedPolygons;
public:
void AddLabels(const vector<Point> &points, const vector<const unsigned int>&polygonVertices);
};
I working on PolygonCutter. i need it to be just a manager that uses a methodAddLabels to set the member _label of each Point in vector points to the integers passed as the vector polygonVertices
How can I do it? I am having trouble because I am not able to access the method setPointLabel(int label) from here:
My try contains the following errors:
void AddLabels(const vector<Point> &points, const vector<const unsigned int>&polygonVertices);
{
int originalNumberOfVertices = points.size();
for(int i = 0; i<originalNumberOfVertices ; i++)
{ int label = polygonVertices[i]; // ERROR type 'const vector<const unsigned int>' does not provide a subscript operator
const Point& point = points[i];
point.setPointLabel(label); // ERROR 'this' argument to member function 'setPointLabel' has type 'const Point', but function is not marked const
}
}
in AddLabels method, vector points is const. setPointLabel is non-const member function. non-const member functions can only be invoked for non-const objects. Either
remove const from const vector &points , or
mark function setPointLabel const.
This question already has answers here:
C++ best practice: Returning reference vs. object
(8 answers)
Closed 5 years ago.
Why do you return an object with function by using &?
For example, lets have a look at the following classes and function:
class Point
{
public:
Point(int x, int y);
int getX() const;
int getY() const;
void setX(int x);
void setY(int y);
void print() const;
private:
int x, y;
};
class Circle
{
public:
Circle(int x, int y, int r, int color);
int getColor() const;
void setColor(int color);
bool contains(const Point &p) const;
void print() const;
private:
const Point center;
int radius, color;
};
class Collection
{
public:
Collection(int radius, int width, int height, int color);
~Collection();
Circle& getCircleAt(const Point &p);
void print() const;
private:
int count;
Circle **circles;
};
Circle& Collection::getCircleAt(const Point &p)
{
for (int i = 0; i < count; i++)
if (circles[i]->contains(p))
return *(circles)[i];
}
The function above returnes a circle.
In the function getCirclet, why is the sign & is necessary ? Why can't I omit it?
In your function
Circle& Collection::getCircleAt(const Point &p)
the return type Circle& means that a reference to on object of type Circle will be returned. If you declared your function
Circle Collection::getCircleAt(const Point &p)
with the same body, then a copy of the object would be returned, if a copy constructor is available. This means in the first case, if you modify the returned object, this will modify the object contained in the Collection, while in the second case, only the copy will be modified.
Note that references cannot be NULL, so you have a problem if your particular function is called with a Point that is not inside any Circle. Returning nothing at all, as you do now, is not an option.
I have defined a point class using dev c++. then I tried to overload cout for this class.
while not using it i get no error. but when i use it in main it gives me this error:
[Linker error] C:\Users\Mohammad\Desktop\AP-New folder\point/main.cpp:12: undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Point const&)'
//point.h
class Point{
private:
double x;
double y;
double z;
public:
//constructors:
Point()
{
x=0;
y=0;
z=0;
}
Point(double xx,double yy,double zz){x=xx; y=yy; z=zz;}
//get:
double get_x(){return x;}
double get_y(){return y;}
double get_z(){return z;}
//set:
void set_point(double xx, double yy, double zz){x=xx; y=yy; z=zz;}
friend ostream &operator<<(ostream&,Point&);
};
//point.cpp
ostream &operator<<(ostream &out,Point &p){
out<<"("<<p.x<<", "<<p.y<<", "<<p.z<<")\n";
return out;
}
//main.cpp
#include <iostream>
#include "point.h"
using namespace std;
int main(){
Point O;
cout<<"O"<<O;
cin.get();
return 0;
}
This is because you did not make your Point a const when declaring and defining your operator. Change your declaration as follows:
friend ostream &operator<<(ostream&, const Point&);
Also add const in the definition:
ostream &operator<<(ostream &out, const Point &p){
out<<"("<<p.x<<", "<<p.y<<", "<<p.z<<")\n";
return out;
}
Note that the code that you posted does not require const-ness of the Point&. Some other code made your compiler or IDE believe that an operator with a const is referenced. For example, using the operator like this would require a const
cout << Point(1.2, 3.4, 5.6) << endl;
(demo)
Since the snippet above creates a temporary object, passing a reference to it as a non-const is prohibited by the C++ standard.
Not directly related to this issue, but you may want to mark the three getters for individual coordinates const as well:
double get_x() const {return x;}
double get_y() const {return y;}
double get_z() const {return z;}
This would let you access coordinates with getters on objects marked const.
My understanding is static member functions can access private, protected members of the class.
Here in my code, sortPoint2DXAsc should be able to access X and Y since it's member function of Point2D. But I get this error:
Point2D.h: In function ‘bool sortPoint2DXAsc(const Point2D&, const Point2D&)’:
Point2D.h:22:7: error: ‘int Point2D::x’ is protected
Point2D.cpp:41:21: error: within this context
Point2D.h:22:7: error: ‘int Point2D::x’ is protected
Point2D.cpp:41:31: error: within this context
Point2D.h:22:7: error: ‘int Point2D::x’ is protected
Point2D.cpp:41:44: error: within this context
Point2D.h:22:7: error: ‘int Point2D::x’ is protected
Point2D.cpp:41:55: error: within this context
Point2D.h:23:7: error: ‘int Point2D::y’ is protected
Point2D.cpp:41:67: error: within this context
Point2D.h:23:7: error: ‘int Point2D::y’ is protected
Point2D.cpp:41:77: error: within this context
Here is my code:
class Point2D
{
protected:
int x;
int y;
public:
//Constructor
Point2D();
Point2D (int x, int y);
//Accessors
int getX();
int getY();
//Mutators
void setX (int x);
void setY (int y);
static bool sortPoint2DXAsc (const Point2D& left, const Point2D& right);
};
bool sortPoint2DXAsc (const Point2D& left, const Point2D& right)
{
return (left.x < right.x) || ((left.x == right.x) && (left.y < right.y));
}
I think you want something like this code tested :
class Point2D {
protected:
int x;
int y;
public:
//Constructor
Point2D();
Point2D (int x, int y);
//Accessors
int getX() const {return x; }
int getY() const {return y;}
//Mutators
void setX (int x) {/*Do something with x*/}
void setY (int y) {/*Do something with y*/}
static bool sortPoint2DXAsc(const Point2D& left, const Point2D& right);
};
bool Point2D::sortPoint2DXAsc (const Point2D& left, const Point2D& right)
{
return (left.getX() < right.getX()) || ((left.getX() == right.getX()) && (left.getY() < right.getY()));
}
You can use static since you're not using this in your function. For example, if you was using this->x instead of left.getX(), you would have received an error because your function is static.
Now, here's a second example where you can access x and y without accessors.
Since you're inside your class definition, x and y are accessible from left and right which are instance of Point2D even if they are protected.
I have two versions of operator():
const A& operator(int x ,int y) const;
A& operator(int x ,int y);
But I don't know what would be the best way to avoid code repetition (because they essentially have the same logic).
I did read the awesome FAQ regarding operator overloading (and some other questions) but did not find answer.
EDIT_1: I've tried the suggestion that Skizz proposed but something like that does not quite work for me but maybe I've missed something:
Because this works while this does not compile giving the following error:
error: invalid initialization of reference of type ‘int&’ from expression of type ‘const value_type {aka const int}’
If both methods 'essentially have the same logic' then surely they should both be marked const. If they do behave differently, should they be called the same thing?
What you need is a third, hidden method that does the common thing, like this:-
const A& operator(int x ,int y) const
{
return Common (x,y);
}
A& operator(int x ,int y)
{
return Common (x,y);
}
A& Common (int x, int y) const
{
// common code
}
This takes advantage of the implicit non-const to const conversion. In the first method, the this object remains const in the call to Common but the non-const return value is converted to const. In the second, the non-const this object is converted to a const this object and the return object is unchanged.
If you have the data in question as shared/unique pointer, you are able to forward it to a common function:
class X {
public:
const A& operator () (int x ,int y) const {
common(data, x, y);
return *data;
}
A& operator () (int x ,int y) {
common(data, x, y);
return *data;
}
private:
void common(std::shared_ptr<T>, int x ,int y) const;
std::shared_ptr<A> data;
};
Now you are able to access the T* via data.get() which is 'T* get() const'.
(Note: I consider the common function a bad design)
You might do, also:
class X {
public:
const A& operator () (int x ,int y) const {
common(x, y);
return data;
}
A& operator () (int x ,int y) {
// ... make mutations
common(x, y);
// ... make mutations
return data;
}
void common(std::shared_ptr<T>, int x ,int y) const;
T data;
};
Or actually, making the data mutable, if it is not breaking logical const:
class X {
const A& operator () (int x ,int y) const {
// ... make mutations on the mutable data, only
return *lazy_evaluated_data;
}
A& operator () (int x ,int y) {
const X& self = *this;
self(x, y);
return *lazy_evaluated_data;;
}
private:
mutable T lazy_evaluated_data; // or a cache
};
Write a helper function and call it from both operators. You'll need to do some const_cast<...>(this) which can be ugly, but it's a common pattern.