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 { ... }
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).
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
I'm learning C++ and we've been assigned the task of implementing Vector3D classes using Stack and Heap memory. By accident, I've noticed that it is possible to access the protected member fields x, y and z of the Vector3DStack object v being passed into the overload + method.
class Vector3DStack
{
public:
Vector3DStack(double, double, double);
double getMagnitude() const;
double getX() const;
double getY() const;
double getZ() const;
Vector3DStack operator + (Vector3DStack);
Vector3DStack operator - (Vector3DStack);
Vector3DStack operator * (double);
Vector3DStack operator / (double);
Vector3DStack operator % (Vector3DStack);
double operator * (Vector3DStack);
protected:
double x, y, z;
};
Why does C++ allow access to the x, y and z protected fields on the Vector3DStack parameter v when they are declared as protected? I would have expected to have to use v.getX(), v.getY() and v.getZ().
Vector3DStack Vector3DStack::operator + (Vector3DStack v)
{
return Vector3DStack (x + v.x, y + v.y, z + v.z);
}
Many thanks,
George
Because you have implemented operator+ function as member function.
In case of
Vector3DStack operator + (const Vector3DStack& v);
it doesn't really matter - it's adding two objects of Vector3DStack class.
It matters if it comes to
Vector3DStack operator * (double s);
In that case you can only have Vector3DStack as left value, so:
...
vec = vec + 5; // is ok
vec = 5 + vec; // isn't
For the second version you need to implement overloading outside the class:
Vector3DStack operator * (double s, const Vector3DStack& v);
Vector3DStack operator * (const Vector3DStack& v, double s);
in that case operator function won't be able to reach private members of class Vector3DStack.
In this case you could declare operator function as friend - friend functions have access to private members of class.
Additional update: you should pass the object by const reference.
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.