I am getting error in the operator overloading definition. The error goes away if I remove the consts in the parameters. Is there any way I can get it working without removing the consts in the parameters? Also what is happening behind them?
class Vector3D{
public:
float x, y, z;
float dot(Vector3D& v) {
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
You should qualify the member function dot as const as well, otherwise you can't call this member function on a const object:
float dot(Vector3D const& v) const { // <-- const here
You also need to accept v by const& since you are passing it a const object.
You didn't include the error, but it says something like : "cannot call non-const method on const object". Your dot does not modify members and should be declared as const also the argument is not modifed, hence should be const:
class Vector3D{
public:
float x, y, z;
// v---------------- allow to call on const objects
float dot(const Vector3D& v) const {
// ^---------------------------------- pass parameters as const ref
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
In the Vector3D::dot function, neither the object for member function call nor the argument object are modified.
To tell this to the compiler, you should add two consts to your dot definition.
class Vector3D{
public:
float x, y, z;
float dot(const /*(1)*/ Vector3D& v) const /*(2)*/ {
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
(1) : telling that the argument object is not modified
(2) : telling that the object for member function call is not modified
Related
I am writing a class for a 2D Vector and need to do a dot product.
I have overloaded the * operator to do this, but when it comes time to perform this * this it gives me an error:
class Vector2 {
private:
float x, y;
public:
Vector2(float _x, float _y) {
x = _x;
y = _y;
}
// Dot product
float operator*(const Vector2& other) {
return x * other.x + y * other.y;
}
// Magnitude (abs)
float Magnitude() {
float dot = (this) * (this); // HERE IS THE ERROR: expression must have arithmetic or unscoped enum type
return std::sqrt(dot);
}
Vector2 operator+(const Vector2& other) {
return Vector2(x + other.x, y + other.y);
}
};
The error is: expression must have arithmetic or unscoped enum type
Any help is appreciated! Thank You :)
The this keyword is a pointer, not an actual object.
The correct code is therefore (*this) * (*this).
now i am stumbling with c++ code problem.
i made a simple structure 'Vector3' in that i defined the operator+.
and when i use that operator inside const function, it show a red line.
struct Vector3 {
float x, y, z;
Vector3 operator+ (const Vector3 v) {
return Vector3(x + v.x, y + v.y, z + v.z);
};
Vector3(float x, float y, float z) : x(x), y(y), z(z) {};
};
// and i use it inside some const function
struct SomeST {
Vector3 a,b;
Vector3 Function() const
{
return a + b; // error
}
};
and if i delete the const from function, it works!
so it would be amazing if someone can explain what's going on under the hood.
thanks.
Function
Vector3 Function() const
is const. Which means, that this is const inside the function. Which in turn means both a and b are const. a + b syntax is fancy way for writing a.operator + (b) (call operator + method on object a with argument b). Now a is const, so a.operator + method must also be const. Since you've not supplied such operator (the operator you've written is not const) your compiler highlights this as error and if you try to compile it, you will get const based error.
You need to suply operator + (...) const, which in this exact case means you need to add const keyword to definition:
Vector3 operator+ (const Vector3 v) const { ... }
g++ can't compile this program because:
"
45:20: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
xxx.cpp:27:15: note: candidate 1: const Point2d Point2d::operator*(float) const
const Point2d Point2d::operator*(float xy) const
xxx.cpp:45:20: note: candidate 2: operator*(double, int) <built-in>
Point2d x = xxx * 3;
"
When I delete "operator double()" then "operator *" works, but is there an option to have those to operators at once?
code:
class Point2d {
public :
Point2d(float x, float y);
const Point2d operator*(float xy) const;
operator double(); //when I delete operator double(), then operator* works
private :
float x;
float y;
};
Point2d::operator double()
{
return sqrt((this->x * this->x) + (this->y * this->y));
}
const Point2d Point2d::operator*(float xy) const
{
return Point2d(x * xy, y * xy);
}
Point2d::Point2d(float x, float y)
{
this->x = x;
this->y = y;
}
int main()
{
Point2d xxx(3, 5.5);
Point2d x = xxx * 3;
return 0;
}
In xxx * 3 the compiler can either convert 3 to float and use operator*(float xy) or convert xxx to double using operator double() and then use the built-in multiplication.
The rules say that this is ambiguous, so it is not allowed to choose either.
When you remove the conversion, one of the options goes away and so it is no longer ambiguous.
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.
I am trying to overload (*,+,-,/,=) opertors in FLOAT class. I wrote this class:
class FLOAT{
private:
float x;
public:
FLOAT(){ x=0.0; }
void setFloat(float f) { x=f; }
void operator+(FLOAT obj) {x=x+obj.x; };
void operator-(FLOAT obj) {x=x-obj.x; };
void operator*(FLOAT obj) {x=x*obj.x; };
void operator/(FLOAT obj) {x=x/obj.x; };
FLOAT& operator=(const FLOAT& obj) {this->x=obj.x; return *this; };
};
and I use it such:
int main() {
FLOAT f,f2,f3;
f.setFloat(4);
f2.setFloat(5);
f3=f+f2;// here is the problem!
system("pause");//to pause console screen
return 0;
}
f3=f+f2 seems not right. What can I do?
I think your implementations of the operators will not do what you want. For example:
FLOAT f1; f1.setFloat(1.0);
FLOAT f2; f2.setFloat(2.0);
FLOAT f3;
f3 = f1 + f2;
Assuming that you change operator+(), for example, to return a FLOAT, you will still have the effect that after the addition, f1 and f3 will both equal 3.0;
A commonly used idiom is to implement the operators like += in the class, and the operators like + outside the class. For example:
class FLOAT {...
FLOAT& operator+=(const FLOAT& f)
{
x += f.x;
return *this;
}
};
...
FLOAT operator+(const FLOAT& f1, const FLOAT& f2)
{
FLOAT result(f1);
f1 += f2;
return f1;
}
A side benefit of this is that you can also easily add other operators like
FLOAT operator+(int x, const FLOAT& f);
FLOAT operator+(double x, const FLOAT& f);
Doing a thorough job on a class like this is good practice for when you want to do this work with more interesting types like complex numbers or matrices. Be sure you add the comparison operators, copy constructor, destructor and assignment operators for completeness. Good luck!
Your operators are the equivalent of +=, -=, etc.
If you want to +, you also need to return a value!
FLOAT operator+(FLOAT obj)
{
FLOAT tmp;
tmp.x = x+obj.x;
return tmp;
}
You can't assign the return value of a void function to anything, because it doesn't return anything. Declaring the operator overloads as friend functions is frequently much more flexible. Your class and functions should be more like this:
class FLOAT {
friend FLOAT operator+( const FLOAT & a, const FLOAT & b );
/* ... rest of class ... */
};
FLOAT operator+( const FLOAT & a, const FLOAT & b )
{
FLOAT temp( a );
temp.x += b.x;
return temp;
}
You should return the result in each case. Also pass an argument by reference so it will not be copied and add some const qualifiers. For + it might look like:
FLOAT operator+(const FLOAT& obj) const
{
FLOAT res;
res.x = x + obj.x;
return res;
}
Note you might not want to return const, as you would like go get modifiable object.
void operator+(FLOAT obj) {x=x+obj.x; };
What is wrong in this code?
It returns void and you want to assign this somewhere. No go.
FLOAT & FLOAT::operator=(const FLOAT &rhs) {
... // todo assignment here
return *this; // Return a reference to myself.
}
FLOAT & FLOAT::operator+=(const FLOAT &rhs) {
... //todo implement compound + operator
return *this; // Return a reference to myself.
}
const FLOAT FLOAT::operator+(const FLOAT &rhs) const {
return FLOAT(*this) += other; //that's already done :)
}
operator+ has return type void. It should probably return a FLOAT.
To clarify by example, void operator+(FLOAT obj) {x=x+obj.x; }; should in stead look like FLOAT operator+(FLOAT obj) { return obj.x + x; }. This is because, as others have pointed out, a function with return type of void cannot return any value. Since operator+ is generally expected to return a value that represents the result of addition, you should return a FLOAT object that holds this result.