I am stuck with regards to the 2 non-member, 2 non-friend multiplication and the addition of the operator overloading functions. I am unsure of how to do it. Could someone please assist in helping me to resolve this? Refer to my codes below. Thank you in advance!
Compiler output:
Point.cpp:208:19: error: passing ‘const CS170::Point’ as ‘this’ argument discards qualifiers [-fpermissive]
return other + value;
^~~~~
Point.cpp: In function ‘CS170::Point CS170::
operator*(double, const CS170::Point&)’:
Point.cpp:215:10: error: ‘double CS170::Point::x’ is private within this context
result.x = value * x;
^
Point.cpp:215:22: error: ‘x’ was not declared in this scope
result.x = value * x;
^
Point.cpp:216:10: error: ‘double CS170::Point::y’ is private within this context
result.y = value * y;
^
Point.cpp:216:23: error: ‘y’ was not declared in this scope
result.y = value * y;
Point.h
#include <iostream> // istream, ostream
namespace CS1100
{
class Point
{
public:
// Point(double X, double Y); // Constructors (2)
explicit Point(double x, double y);
Point();
Point operator+(const Point& other)const ;
Point& operator+(double value);
Point operator*(double value) ;
Point operator%(double value);
Point operator-(const Point& other)const ;
Point operator-(double value);
Point operator^(const Point& other);
Point operator+=(double value);
Point& operator+=(const Point& other) ;
Point& operator++();
Point operator++(int);
Point& operator--();
Point operator--(int);
Point& operator-();
// Overloaded operators (14 member functions)
friend std::ostream &operator<<( std::ostream &output, const Point &point );
friend std::istream &operator>>( std::istream &input, Point &point );
// Overloaded operators (2 friend functions)
private:
double x; // The x-coordinate of a Point
double y; // The y-coordinate of a Point
// Helper functions
double DegreesToRadians(double degrees) const;
double RadiansToDegrees(double radians) const;
};
// Point& Add(const Point& other); // Overloaded operators (2 non-member, non-friend functions)
// Point& Multiply(const Point& other);
Point operator+( double value, const Point& other );
Point operator-( double value, const Point& other );
My source code:
///////////////////////////////////////////////////////////////////////////////
// 2 non-members, non-friends (operators)
double operator+( double value, const Point& other )
{
return other + value;
}
double operator*( double value, const Point& other )
{
Point result;
result.x = value * x;
result.y = value * y;
return result;
}
As far as I understand the discussion to the question, the problem is not really the operators themselves, but the number of allowed member functions being limited – and you already have exceeded this limit.
However, you have quite a number of functions that don't need to be members, for instance:
class Point
{
public:
Point operator+(const Point& other) const
{
return Point(x + other.x, y + other.y);
}
};
Make free functions from all these:
class Point { /*...*/ };
Point operator+(Point const& l, Point const& r)
{
return Point(l.getX() + r.getX(), l.getY() + r.getY());
}
Having moved out all these operators like the one shown above, you get away far enough from the limit so that you can introduce the needed getters:
class Point
{
public:
double getX() { return x; };
double getY() { return y; };
};
If you are willing to rename the member variables, e. g. by adding a prefix, you can follow another pattern:
class Point
{
double m_x, m_y;
public:
double x() { return m_x; };
double y() { return m_y; };
void x(double v) { m_x = v; }; // the corresponding setter
// (for illustration, you might not need it)
};
This latter pattern is quite common, too. Advantage is being shorter for skipping the explicit get or set prefix, disadvantage is exactly losing this explicitness... Decide you, which one you prefer. More important than personal preference is consistency, though, so if there's e. g. a company's convention or common practice, follow that one...
Some of your operators will need to remain members, though, these are all those that modify the current object:
class Point
{
public:
Point& operator+=(const Point& other) /* const */ // NEEDS to be non-const
{
x += other.x;
y += other.y;
return *this; // <- very good hint to spot the ones needing to stay members
}
};
If you have a public copy constructor, you can re-use the operator+= for defining the operator+:
class Point
{
public:
Point(Point const& other) : Point(other.x, other.y) { }
};
Point operator+(Point const& x, Point const& y)
{
Point r(x); // or Point(x.x(), x.y()), if you lack such constructor)
r += y;
return r;
}
Actually, you can even spare the explicit copy by accepting one of the parameters by value:
Point operator+(Point x, Point const& y)
// ^ no reference
{
return x += y;
}
The latter rather for illustration, I'd prefer the two references in given case to keep the symmetry of the interface...
Related
I'm supposed to do an overloading of the modulus function, but I'm not sure how to do it. Let me know if you require more information.
This is my requirement by my school:
Member function that rotates a Point about the origin by the specified number of degrees. Returns a new Point
Inside the driver file, my school wants the modulus function to accomplish this scenario:
Point pt1(-50, -50);
double angle = 45;
Point pt2 = pt1 % angle;
This is what I've tried:
Point Point::operator%( int value)
{
(int)x%value;
(int)y%value;
return *this;
}
//point.h file
class Point
{
public:
// Constructors (2)
explicit Point(double x, double y);
Point();
double getX() const;
double getY() const;
Point operator+(const Point& other)const ;
Point& operator+(double value);
Point operator*(double value) ;
Point operator%(int value);
Point operator-(const Point& other)const ;
Point operator-(double value);
Point operator^(const Point& other);
Point operator+=(double value);
Point& operator+=(const Point& other) ;
Point& operator++();
Point operator++(int);
Point& operator--();
Point operator--(int);
Point& operator-();
// Overloaded operators (14 member functions)
friend std::ostream &operator<<( std::ostream &output, const Point
&point );
friend std::istream &operator>>( std::istream &input, Point
&point );
// Overloaded operators (2 friend functions)
private:
double x; // The x-coordinate of a Point
double y; // The y-coordinate of a Point
// Helper functions
double DegreesToRadians(double degrees) const;
double RadiansToDegrees(double radians) const;
};
// Point& Add(const Point& other); // Overloaded operators (2 non-member, non-friend functions)
// Point& Multiply(const Point& other);
Point operator+( double value, const Point& other );
Point operator-( double value, const Point& other );
The first error I see is that you didn't respect the requirements of your assignement. Your assignement specifically ask for your type to support this operation:
Point pt1{-50, 50};
Point pt2 = pt1 % 45.5;
This infer that your operator must return a point with the operation apply to it using a double. You clearly store the angle as double, but receive an int. That is not respecting your requirement. Also, you return a rotated point, but not the right one. You're making the operation in-place instead of making the operation on a new point. Inside your operator, you should create a point with the new position. Something like this:
Point Point::operator%(double) const {
return Point{..., ...};
}
Then, your operation is wrong. You cast the point data member to intonly to do a modulo on them. A modulo don't do a rotation. A rotation is usually done with a sine and a cosine. You cannot use the C++ %operator on int to make a rotation.
I'm creating a 2D coordinate class (named “Point”) to help me learn C++. I want to be able to perform basic arithmetic operations (+, -, *, / ...) on Point class objects (e.g. Point_a + Point_b). However, I also want to be able to perform such operations between Points and other variable types (int/float/double).
This can be done using operator/function overloading. It can be seen from my code below (addition only) that I must, as far as I am aware, include two additional functions for each additional variable type, one for the “Point + int/float/double” form and one for the “int/float/double + Point” form.
#include <iostream>
using namespace std;
class Point
{
private:
double x, y;
public:
Point(double x_in, double y_in){
setX(x_in);
setY(y_in);
}
// Getters and Setters omitted for brevity
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(const Point &p1, const Point &p2); //Point + Point
friend Point operator+(const Point &p1, int val); //Point + Int
friend Point operator+(int val, const Point &p1); //Int + Point
friend Point operator+(const Point &p1, float val); //Point + Float
friend Point operator+(float val, const Point &p1); //Float + Point
friend Point operator+(const Point &p1, double val); //Point + Double
friend Point operator+(double val, const Point &p1); //Double + Point
// --- End of Addition Operator Overloads --- (Code Block A)
};
// --- Start of Addition Operator Overload Functions --- (Code Block B)
Point operator+(const Point &p1, const Point &p2){
return Point(p1.x + p2.x, p1.y + p2.y);
}
Point operator+(const Point &p1, int val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(int val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
Point operator+(const Point &p1, float val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(float val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
Point operator+(const Point &p1, double val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(double val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
// --- End of Addition Operator Overload Functions --- (Code Block B)
int main()
{
Point point_a( 2.00, 20.00);
Point point_b( 0.50, 5.00);
Point point_c = point_a + point_b;
cout << "X = " << point_c.getX() << " and Y = " << point_c.getY() << endl;
return 0;
}
There seems to be a lot of repetition, particular between “Point + int/float/double” type functions. I was wondering if there is a way that this could be shorted a little. Say, rather than having individual versions for integer, float and double I could have one version which would handle all three. For example converting code blocks "A" and "B" into something like:
...
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(const Point &p1, const Point &p2); //Point + Point
friend Point operator+(const Point &p1, int||float||double val); //Point + Int/Float/Double
friend Point operator+(int||float||double val, const Point &p1); //Int/Float/Double + Point
// --- End of Addition Operator Overloads --- (Code Block A)
...
...
// --- Start of Addition Operator Overload Functions --- (Code Block B)
Point operator+(const Point &p1, const Point &p2){
return Point(p1.x + p2.x, p1.y + p2.y);
}
Point operator+(const Point &p1, int||float||double val){
return Point(p1.x + val, p1.y + val);
}
Point operator+(int||float||double val, const Point &p1){
return Point(p1.x + val, p1.y + val);
}
// --- End of Addition Operator Overload Functions --- (Code Block B)
...
The above code section is intended to be representational of the desired result rather than actually functional (e.g. int OR float OR double).
In short, is there any way that I can make "friend Point operator+(const Point &p1, int val);" and its corresponding function (in code block B) accept integer, float and double values, or do I need to have an individual one for each variable type?
Thank you for your time.
Other answers mention templates but in actual fact, all numeric types will automatically be promoted to doubles.
Therefore, you only need to provide operators in terms of Point and double.
#include <iostream>
using namespace std;
class Point
{
private:
double x, y;
public:
Point(double x_in, double y_in){
setX(x_in);
setY(y_in);
}
// Getters and Setters omitted for brevity
double getX() const { return x; }
double getY() const { return y; }
void setX(double v) { x = v; }
void setY(double v) { y = v; }
// unary ops
Point& operator+=(Point const& other)
{
x += other.x;
y += other.y;
return *this;
}
Point& operator+=(double v)
{
x += v;
y += v;
return *this;
}
// --- Start of Addition Operator Overloads --- (Code Block A)
friend Point operator+(Point p1, const Point &p2)
{
p1 += p2;
return p1;
}
friend Point operator+(Point p1, double val)
{
p1 += val;
return p1;
}
friend Point operator+(double val, Point p1)
{
p1 += val;
return p1;
}
// --- End of Addition Operator Overloads --- (Code Block A)
};
// --- End of Addition Operator Overload Functions --- (Code Block B)
int main()
{
Point point_a( 2.00, 20.00);
Point point_b( 0.50, 5.00);
Point point_c = point_a + point_b;
point_c += 10;
Point point_d = point_c + 10;
Point point_e = point_d + 10.1;
cout << "X = " << point_c.getX() << " and Y = " << point_c.getY() << endl;
return 0;
}
Such can be more generalized by using templates and specializing the exceptional case, instead of providing an overloaded version for each and every matching type:
class Point
{
public:
// ...
template<typename T>
friend Point operator+(const Point &p1, T p2);
};
template<typename T>
Point operator+(const Point &p1, T val){
static_assert(std::is_artithmetic<T>::value,"An arithmetic type is required");
return Point(p1.x + val, p1.y + val);
}
// Specialization for Point
template<>
Point operator+(const Point &p1, const Point& val){
return Point(p1.x + val, p1.y + val);
}
Separate solution than the template solution is to define constructors for the types you want to support, and have a single operator+ that works on Point types.
The compiler will implicitly call the proper constructor to convert the built-in type, before invoking operator+.
This simplifies the implementation, at the expense of wasted temp objects.
// Example program
#include <iostream>
#include <string>
class Point {
private:
double x, y;
public:
Point(int val) {
this->x = val;
this->y = val;
}
Point(double x, double y) {
this->x = x;
this->y = y;
}
friend Point operator+(const Point &p1, const Point &p2) {
return Point(p1.x + p2.x, p1.y + p2.y);
}
};
int main()
{
Point p(1,2);
Point q = p + 10;
Point v = 10 + p;
}
There is a stylistic argument about explicitly white-listing supported types via the constructors, and blacklisting via static_asserts.
You can absolutely do this using templates:
// inside the class
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
friend Point operator+(const Point &p1, T val) {
// function definition
}
// Don't forget to define the function for T on the left hand side
This uses std::enable_if and std::is_arithmetic, to make this function only accept types that are "arithmetic types", basically integers and floats.
Point's operator+ implementations all converts its non-Point arguments to doubles before doing a + on elements.
The float and int overloads are nearly pointless. Just write the two double overloads.
Built-in conversion from int and float will then occur in the operator+ call.
If you really need int/float overloads and you know why and have tested that the double overload doesn't work, consider fixing the broken template conversion operator which is about the only way I can see this bbeing the case.
Failing that, cast to double explicitly.
Failing that, maybe write a template + that takes any T convertible to double, then converts and calls the above + for double. Then add a paragraph of documentation why you had to do something this stupid and complex instead of just overloading + with double. Then read that paragraph and change your mind and stick with + overloaded with double.
#include <iostream>
using namespace std;
class Point {
private:
int x, y; // Private data members
public:
Point(int x = 0, int y = 0); // Constructor
int getX() const; // Getters
int getY() const;
void setX(int x); // Setters
void setY(int y);
void print() const;
const Point operator+(const Point & rhs);
// Overload '+' operator as member function of the class
};
int main(int argc, char** argv)
{
Point p1(1, 2), p2(4, 5);
// Use overloaded operator +
Point p3 = p1 + p2;
p1.print(); // (1,2)
p2.print(); // (4,5)
p3.print(); // (5,7)
// Invoke via usual dot syntax, same as p1+p2
Point p4 = p1.operator+(p2);
p4.print(); // (5,7)
// Chaining
Point p5 = p1 + p2 + p3 + p4;
p5.print(); // (15,21)
return 0;
}
// Constructor - The default values are specified in the declaration
Point::Point(int x, int y) : x(x), y(y) { } // Using initializer list
// Getters
int Point::getX() const { return x; }
int Point::getY() const { return y; }
// Setters
void Point::setX(int x) { this->x
= x; } // (*this).x = x; x = x
void Point::setY(int y) { this->y = y; }
// Public Functions
void Point::print() const {
cout << "(" << x << "," << y << ")" << endl;
}
// Member function overloading '+' operator
const Point Point::operator+(const Point & rhs) {
return Point(x + rhs.x, y + rhs.y);
}
I'm studying operator overloading and I don't understand why I get the error.
error: no match for 'operator+' (operand types are 'const Point' and 'Point')
I deleted const qualifier at the end of the operator+ function on purpose in order to understand it. Can someone explain explicitly why I need it?
The member
const Point Point::operator+(const Point & rhs);
is a non-const member, i.e. requires the lhs of the operation to be mutable, but (as the error message shows) you require an operation with a const lhs. Hence, you must declare the operator as such
Point Point::operator+(const Point & rhs) const;
Note that I also removed the const for the return type, as it is deprecated.
Why do you need the const? The natural + operator (for example between arithmetic types) does not alter its arguments and, as a consequence, the usual (human) conventions for using this operator implicitly assume that the arguments are not altered. In your particular case, the return of a+b was explicitly const (though that is deprecated AFAIK), so that in a+b+c = (a+b)+c the lhs is const and your non-const member function cannot be used.
Moreover, whenever a member function does not alter the state of its object, it should be declared const, so that it can be called for const object.
Alternatively, this operator can be defined as non-member function friend
Point operator+(const Point&lhs, const Point&rhs);
which more clearly expresses the symmetry between lhs and rhs (the corresponding function for your non-const member would have been
Point operator+(Point&lhs, const Point&rhs);
).
You need to define your method as a constone, i.e.:
const Point operator+(const Point & rhs) const;
p1+p2 returns a const Point so you need a const Point + const Point operator to be able to compute (p1+p2)+p3.
Good answers, but they don't explain why the const is an issue. The simple reason is chaining order and operator type matching.
Point p5 = p1 + p2 + p3 + p4;
// is interpreted as:
Point p5 = ConstPoint( (Point(p1)).operator+((const Point&)(p2)) + p3 + p4;
// as operator+ is left-to-right , not right-to-left !!!
Point and const Point are different types, so in the first iterpretation, you have a:
p5 = const Point(sumP1P2) . operator+ (Point(P3)) /*+ P4 awaiting interpretation */;
// whose search will be for a const LHS - i.e. "Point operator=(constPointRef) const;" - which is bound to fail.
The following will work:
const P& operator+(const P& rhs) const; // corresponds to const P& result = const P& lhs + const P& rhs
P operator+(P rhs) const; // corresponds to copy-by-value for all operands.
The only problem is "const" Point operator+(const Point & rhs); remove that in the def and dec .. it will work
Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;
How can I modify the following code in such way I don't need to repeat f2=11;
f3=12; in the main function. The code is for overloading the most common operators.
class FLOAT{
private:
float x;
public:
FLOAT(){ x=0.0; }
void setFloat(float f) { x=f; }
float getFloat() { return x;};
FLOAT operator+(FLOAT obj) {x=x+obj.x; return *this;};
FLOAT operator-(FLOAT obj) {x=x-obj.x; return *this;};
FLOAT operator*(FLOAT obj) {x=x*obj.x; return *this;};
FLOAT operator/(FLOAT obj) {x=x/obj.x; return *this;};
FLOAT& operator=(const FLOAT& obj) {this->x=obj.x; return *this; };
FLOAT& operator=(const float& y) {this->x=y; return *this; };
};
int main() {
FLOAT f,f2,f3;
f2=11;
f3=12;
f=f3-f2;
cout<<"f3-f2 ="<<f.getFloat()<<endl;
f2=11;
f3=12;
f=f3+f2;
cout<<"f3+f2 ="<<f.getFloat()<<endl;
f2=11;
f3=12;
f=f3*f2;
cout<<"f3*f2 ="<<f.getFloat()<<endl;
f2=11;
f3=12;
f=f3/f2;
cout<<"f3/f2 ="<<f.getFloat()<<endl;
system("pause"); // to pause console screen
return 0;
}
#Oli's answer pretty much says you what minimal thing you need to do in order to make your code work. However, I see (and I know even #Oli sees) that your implementation of the class has many flaws.
Since you've implemented FLOAT, I'm explaining you the implementation of Double (the implementation of FLOAT would be similar).
class Double {
double data;
public:
Double (double p=0.0) : data(p){}
double value() { return data; }
Double & operator+=(Double const & other)
{
data += other.data;
return *this;
}
Double & operator-=(Double const & other)
{
data -= other.data;
return *this;
}
//...
};
Note that you don't need to implement operator=(Double const&) and Double(Double const&). The compiler generated ones would be enough. Since the constructor takes one argument of type double, you don't need to implement operator=(double const &) also. The compiler generated copy-semantics, along with the constructor, would take care of that.
Now see this,
//implement operator+ and operator- as non-member functions
Double operator+(Double a, Double const & b)
{
a += b; //a is local copy, so we can change it
return a;
}
Double operator-(Double a, Double const & b)
{
a -= b; //a is local copy, so we can change it
return a;
}
Note that I've implemented operator+ and operator- in terms of operator+= and operator-= respectively.
Similarly, you can implement operator/= and operator*= as member functions, and then implement operator/ and operator* in terms of the them!
Your operators should create a new instance; they shouldn't be modifying themselves (in fact, they should be declared const to prevent this).
e.g.:
FLOAT operator+(FLOAT obj) const
{
FLOAT tmp;
tmp.setFloat(x + obj.x);
return tmp;
}
Note there are much more idiomatic ways of defining operator overloads (e.g. defining operator+ in terms of operator+=, and defining a constructor that takes a float). But the above should suffice.