This question already has answers here:
overloading operator * c++
(2 answers)
Closed 9 years ago.
I am trying to make a vector class in c++. I have overloaded the * operator like this:
class vector2
{
public:
vector2(float x, float y);
static vector2 vector_zero;
float x, y;
float length() const;
string to_string();
vector2 operator+(vector2 other);
vector2 operator*(float other);
};
vector2 vector2::operator*(float other)
{
return vector2(x * other, y * other);
}
It works fine when I write "vector2(3,4) * 2" but I want it to work when I write "2 * vector(3,4)" too.
How can I do that?
You need to create another operator* (outside of the class) like this:
vector2 operator*(float other, vector2 v){
return v*other;
}
Side note:
you forgot a lot of the const declarations, an I also recommend using reference (&) for classes. I would also make these functions inline, because they are so small:
class vector2
{
public:
...
string to_string() const;
inline vector2 operator+(const vector2 &other)const;
inline vector2 operator*(float other)const;
};
inline vector2 operator*(float other, const vector2 &v){
return v*other;
}
Related
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 7 months ago.
Imagine you have the following code:
Vector3D class{
public:
Vector3D(double=0, double=0, double=0);
Vector3D(const Vector3D& v){x = v.x;y = v.y;z = v.z;}
private:
double x,y,z;
}
And I wanna add two vectors:
Vector3D a(1,2,1);
Vector3D b(2,4,2);
Vector3D c = a + b;
How can I do that without modifying neither of them...
I thought of this:
Vector3D class{
public:
Vector3D(double=0, double=0, double=0);
Vector3D(const Vector3D& v){x = v.x;y = v.y;z = v.z;}
Vector3D(const Vector3D& v, const Vector3D& f){
x = v.x + f.x;
y = v.y + f.y;
z = v.z + f.z;
}
private:
double x,y,z;
}
However, this error appears...
"error: ‘Vector3D& Vector3D::operator+(const Vector3D&, const Vector3D&)’ must have either zero or one argument ..."
I know that I can only add one argument to the method within a class, but how can I work around this issue in order to add these two vectors without modfying neither?
Thank you in advance!
You created a constructor that takes two Vector3D:
Vector3D(const Vector3D& v, const Vector3D& f)
so you can use that:
Vector3D c(a, b);
An alternative way is defining operator+ in your class Vector3D like this:
Vector3D operator+(const Vector3D& other) const {
return Vector3D(x + other.x, y + other.y, z + other.z);
}
I'm learning C++ and specifically the operator overloading.
I have the following piece of code:
#include <iostream>
#include <string>
using namespace std;
class Vector2
{
private:
float x, y;
public:
Vector2(float x, float y)
: x(x), y(y) {}
Vector2 Add(const Vector2& other) const;
Vector2 operator+(const Vector2& other) const;
Vector2 operator*(const Vector2& other) const;
friend ostream& operator << (ostream& stream, const Vector2& other);
Vector2 Multiply(const Vector2& other) const;
};
ostream& operator << (ostream& stream, const Vector2& other)
{
stream << other.x << ", " << other.y;
return stream;
}
Vector2 Vector2::Add(const Vector2& other) const
{
return Vector2(x + other.x, y + other.y);
}
Vector2 Vector2::operator+(const Vector2& other) const
{
return Add(other);
}
Vector2 Vector2::Multiply(const Vector2& other) const
{
return Vector2(x * other.x, y * other.y);
}
Vector2 Vector2::operator*(const Vector2& other) const
{
return Multiply(other);
}
int main()
{
Vector2 position(4.0f, 4.0f);
Vector2 speed(0.5f, 1.5f);
Vector2 powerup(1.1f, 1.1f);
Vector2 result = position.Add(speed.Multiply(powerup));
Vector2 result2 = position + speed * powerup;
std::cout << result2 << std::endl;
std::cin.get();
}
Question: if I want this to work, I need to declare my ostream& operator << as friend. Otherwise MS Studio tells me: "Function definition for operator << not found"!
I don't understand why. I don't need to declare the other operators as friend, so why is this necessary in this case?
Thanks.
The operator<< must be defined as non-member function (as well as operator>>).
Let's take a look at the case when our class has defined the operator<< as a member function, we would have to do output like so:
// Member function, lhs is bound to implicit this
ostream& operator<<(ostream&) const;
Myclass obj;
obj << std::cout;
Why so? Because you know that an overloaded operator is just a function. So, underlying call to this function looks like this:
obj.operator<<(std::cout);
If the operator is a member function, there's no other way. Since we can't modify the library.
So, in order for the operator to access private data members, i.e. the x and y, we have to declare it as a friend.
The arithmetic operators ordinarily should also be non-member functions, to allow conversions for either of the operands. Thought it is not required. These also should not change state of their operands and should produce a new value, which also stimulates to approach them from non-member function.
Also, I would advise you to get rid of the using namespace std and specify namespaces explicitly (or at least avoid mixing up).
Operators + and * are declared as member functions of Vector2, so they are naturally able to access private members of Vector2.
However, you can't declare canonical IO-operators (<< and >>) as member-functions. The line
friend ostream& operator << (ostream& stream, const Vector2& other);
is not a declaration of a member function. It simply allows the free/non-member function ostream& operator << (ostream& stream, const Vector2& other); to access private members of Vector2.
Without this line you should get the error
'Vector2::x': cannot access private member declared in class 'Vector2'
(or something similar)
However, the error
"Function definition for operator << not found"
could arise when you have split declaration and definition in your real code. If you have the line
friend ostream& operator << (ostream& stream, const Vector2& other);
in Vector2 you also declared a free function ostream& operator << (ostream& stream, const Vector2& other); and simultaneously make it a friend of Vector2.
If you remove this line, the function isn't declared anywhere. (Of course the last part is only speculation, but the best guess I've got)
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...
This question already has answers here:
Can't Overload operator<< as member function
(3 answers)
Closed 4 years ago.
I have a struct that represents a 2d column vector. I've overloaded some operators such as * to mean scalar multiplication in the context of an int and + to mean vector addition in the context of another vector.
I also want to overload the << operator so that I can simply pass the object to cout and have the two elements printed. Currently I am overloading it like below;
struct vector2d
{
private:
float x;
float y;
public:
vector2d(float x, float y) : x(x), y(x) {}
vector2d() : x(0), y(0) {}
vector2d operator+(const vector2d& other)
{
this->x = this->x + other.x;
this->y = this->y + other.y;
return *this;
}
vector2d operator*(const int& c)
{
this->x = this->x*c;
this->y = this->y*c;
return *this;
}
friend std::ostream& operator<<(std::ostream& out, const vector2d& other)
{
out << other.x << " : " << other.y;
return out;
}
};
This works fine, but if I remove the friend keyword I get "too many parameters for this operator function". What does this mean and why does the friend keyword fix it?
With the friend, the operator is not a member of the class, so it requires 2 input parameters.
Without the friend, the operator becomes a member of the class, and thus requires only 1 parameter, so you would need to remove the vector2d parameter and use the hidden this parameter instead.
I'm trying to build for android some C++ code, that already working on win32. I have a problem, with overloaded operators. For example:
Code:
Vector2 uv0 = textures.back()->m_uv0;
Vector2 uvt = textures.back()->m_uvt;
uv0 = m_uv0 + Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y) + Vector2(0.01f,0.01f);
Where Vector2 is a class declarated above. The declaration of it is:
class Vector2
{
public:
//Constructors
Vector2() : x(0.0f), y(0.0f){}
Vector2(GLfloat _x, GLfloat _y) : x(_x), y(_y) {}
Vector2(double _x, double _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(int _x, double _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(double _x, int _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(int _x, int _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(GLfloat * pArg) : x(pArg[0]), y(pArg[1]) {}
Vector2(const Vector2 & vector) : x(vector.x), y(vector.y) {}
//Vector's operations
GLfloat Length();
Vector2 & Normalize();
Vector2 operator + (Vector2 & vector);
Vector2 & operator += (Vector2 & vector);
Vector2 operator - ();
Vector2 operator - (Vector2 & vector);
Vector2 & operator -= (Vector2 & vector);
Vector2 operator * (GLfloat k);
Vector2 & operator *= (GLfloat k);
Vector2 operator / (GLfloat k);
Vector2 & operator /= (GLfloat k);
Vector2 & operator = (Vector2 vector);
Vector2 Modulate(Vector2 & vector);
GLfloat Dot(Vector2 & vector);
void Set(GLfloat _x, GLfloat _y);
//access to elements
GLfloat operator [] (unsigned int idx);
//data members
float x;
float y;
};
The definition of this class I won't list here, because it doesn't metter.
But unfortunately I recive an error:
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp: In member function'void Sprite::AddTex(TEX::GUItex)':
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp:103:57: error: no match for 'operator+' in '((Sprite*)this)->Sprite::m_uv0 + Vector2((uv0.Vector2::x *((Sprite*)this)->Sprite::m_uvt.Vector2::x), (uv0.Vector2::y * ((Sprite*)this)->Sprite::m_uvt.Vector2::y))'
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp:103:57: note: candidates are:
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/SBMath.h:38:10: note: Vector2 Vector2::operator+(Vector2&)
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/SBMath.h:38:10: note: no known conversion for argument 1 from 'Vector2' to 'Vector2&'
But, if I rewrite the code above like this:
Vector2 uv0 = textures.back()->m_uv0;
Vector2 uvt = textures.back()->m_uvt;
Vector2 vec1 = Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y);
Vector2 vec2 = Vector2(0.01f,0.01f);
uv0 = m_uv0 + vec1 + vec2;
There wouldn't be any errors during compilation.
I can't understand, what is the cause of this silly error.
I would be very pleased, if you explain me how to solve this problem.
It is not possible to bind an r-value to a non-const reference.
This line:
uv0 = m_uv0 + Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y) + Vector2(0.01f,0.01f);
is equivalent to: (I replaced the parameters with PARAMS to make my example more readable):
uv0 = (m_uv0.operator+(Vector2(PARAMS))).operator+(Vector2(PARAMS));
Here Vector2(PARAMS) will create a temporary object. That is you are trying to pass an r-value reference to your operator overload and the compiler will not find a match as your operator is declared as:
Vector2 operator+ (Vector2& vector);
For more info about why temporaries can't be bound to non-const references see this: How come a non-const reference cannot bind to a temporary object?
In the second example you first declare two Vector2 objects and then pass them to the operator as l-value references which matches your operator overload.
One way to solve the issue and let the operator overload take both l-value and r-value references is to declare it as taking a reference to const as it is perfectly fine to bind an r-value to a reference to const. See the answer by krsteeve for how this can be done.
In general you should always declare functions taking references as taking reference to const if you don't intend to modify the argument.
Examples of reference binding:
Vector2& ref1 = Vector2(); // Error, trying to bind r-value to non-const ref.
Vector2 v;
Vector2& ref2 = v; // OK, v is an l-value reference.
// It is however OK to bind an r-value to a const reference:
const Vector& ref3 = Vector2(); // OK.
You're trying to pass in temporary objects as non-const references. Change the signature of your operator + to take a const references:
Vector2 operator + (const Vector2 & vector);
The reason your second sample works is that you're now naming the Vector2 objects, they're no longer temporary.