Const correctness and operator * - c++

I defined a class like this:
Quaternion& conjugate(); //negates the vector component of the quaternion
Quaternion conjugate() const; //same but in without modifying the class...
Quaternion& operator = (Quaternion const& Qrhs);
Quaternion& operator *= (Quaternion const& Q);
Quaternion operator * (Quaternion const& Qrhs) const;
now I use this functions like this:
PRINTVAR(*this); //this is the first time printed (a little macro to print line and file)
Quaternion vQ(0.,vn), resQ;
resQ = vQ*(this->conjugate()); //this is the method I want to discuss...
PRINTVAR(*this); //this is the second time
resQ = *this * resQ;
and this is the output
*this: (0:0:0:0) at line: 128 in file: Quaternions.cpp
*this: (-0:-0:-0:0) at line: 131 in file: Quaternions.cpp
I thought that by calling the operator * in the line resQ = vQ*(this should be called as const)...
why if I print *this again is changed?
here is the definition of the conjugate function:
Quaternion& Quaternion::conjugate(){
/* Given: Nothing
* Task: Invert sign of the vector
* Return: the class which will be modified
*/
V3 vec;
vec = -(this->getVector());
x() = vec[0];
y() = vec[1];
z() = vec[2];
return *this;
}
Quaternion Quaternion::conjugate() const{
Quaternion result(*this);
result.conjugate();
return result;
}

If the code you showed is in a non-const method, than the this pointer is non-const, and the non-const conjugate method is of course a better match than the const one. Return types aren't considered in overload decisions. If you want to insist that the const version is used, you can add constness: resQ = vQ*(static_cast<const Quaternion*>(this)->conjugate());

Probably the method in which you are using this is non-const.
The type of this a member function of a type A, is A * const. For const member function it is const A * const.
Therefore, your code will work as you expect it to do if you enter your code into const method.
If you want to force calling const overload of function you will need to do a const-cast:
const_cast<const Quaternion * const>(this)->conjugate();

*this is not const (although it is used in a const method), and the c++ FAQ Lite states regarding const overloading (in the FAQ's case on a subscript operator);
When you apply the subscript operator to a MyFredList object that is
non-const, the compiler will call the non-const subscript operator.
Translated, since *this is non-const, the non-const method will be called.

Related

Can I only have const overloaded operator member function?

I'm implementing a fraction class, and need to overload arithmetic operators.
The problem is, can I only implement a const version.
For example, addition:
Fraction operator+( const Fraction& other ) const;
Since both non-const, and const Fraction objects can call this function, do I still need to have an non-const operator+ member function?
const member functions can be called on non-const objects, so no, you don't need a non-const overload.
Fraction a, b;
Fraction c = a + b; // no problem
In general, this kind of problem is better solved with a member operator+= and a nonmember operator+, like this:
class Fraction {
public:
const Fraction& operator+=(const Fraction&);
};
Fraction operator+(const Fraction& lhs, const Fraction& rhs) {
Fraction res(lhs);
res += rhs;
return res;
}
No. You can call const methods over non-const objects, exactly as you can have const references bind to non-const objects. IOW, you can always pass an object that you can modify to code that promises not to modify it - there's no loss of safety. The opposite of course is not true - if you have a const object (=> an object you promised not to modify) you cannot pass it to code that doesn't adhere to this promise.

Multiplication operator overloading

I am implementing a class Vector and defined the multiplication operator as a member of the class as
Vector operator*(const float& s);
as far as I understand, this means that the left operand is a Vector and the right operand is a float. So if I try and do something like this
Vector c(1,2,3);
Vector d = c * 2.0f; // Results in d = (2,4,6)
that's ok, however, to my eyes is weird to see first the vector then the scaling factor, so in order to have float * Vector I defined a non-member function as
Vector operator*(const float& s, const Vector& v)
{
//Invalid operands to binary expression 'const Vector' and 'float'
return v * s;
}
However I received the error in the comment. I don't know what am I missing or if this is not the way I should declare the operator in order to do the scaling in float * Vector fashion.
Notice that you're passing v as const Vector &, but your member operator* is not marked as const. So it can only be called on non-const Vector objects. This is most certainly not what you want, so just mark the member as const:
Vector operator*(const float& s) const;

invalid initialization of non-const reference

Alright, I'm trying to figure out this error and have, so far, had absolutely no luck. I'm doing this for homework, which is why I'm not using included classes.
Here's the relevant code:
//Will return an array where each element is the sum of the respective sums in the added arrays
Vec& Vec::operator+(Vec& v2) const{
Vec ret();
if(mySize>0){
Vec ret(mySize);
for(unsigned i = 0;i<mySize;i++){
ret[i]=v2[i]+myArray[i];
}
}
else{
}
return ret;
}
And from the .h file...:
Vec& operator+ (Vec& v2) const;
This throws the error: "invalid initialization of non-const reference of type ‘Vec&’ from an rvalue of type ‘Vec (*)()’"
I'm completely new to C++, so any help would be appreciated.
Vec ret();
Is taken to be a forward declaration of a function which takes no arguments and returns a Vec. See: the most vexing parse.
Next, you're returning a reference to a local variable, which is bad. ret goes out of scope as soon as the function returns.
The actual error is that you are declaring a function inside of your operator, instead of declaring a Vec object.
Vec ret();
You can fix that by omitting the ():
Vec ret;
Besides that, you have a fundamental design error in that you are attempting to return a reference to a variable which is local to the scope of your operator, resulting in a dangling reference. The usual way to express an addition operator is to have it return a new object, and is typically implemented as a non-member function with a signature such as
Vec operator+(const Vec& lhs, const Vec& rhs);
This can be implemented in terms of an increment member operator
Vec& operator+=(const Vec& rhs);
This one can return a reference to this hence no dangling reference. An example implementation od operator+ would then be
Vec operator+(Vec lhs, const Vec& rhs)
{
return lhs += rhs;
}
As others have stated your initial declaration of ret which you think is default constructing a Vec is actually forward delcaring a function which takes no arguments and returns a Vec. AKA the most vexing parse.
Also the variable shadowing of 'ret' inside the if statement means that you are not modifying the variable that you are expecting to return. It's likely that you want something more like this:
Vec Vec::operator+(const Vec& v2) const{
Vec ret(mySize);
if(mySize>0){
for(unsigned i = 0;i<mySize;i++){
ret[i]=v2[i]+myArray[i];
}
}
else{
}
return ret;
}

Function outside of class in C++ [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Operator overloading outside class
I'm not great with C++ but I've been tasked with creating a custom Vector class that uses a lot of operator overloads. I'm having a hard time grasping how to do one of them.
The class should provide functions for the following:
v3 = v2 * 2.0f;
v3 = 2.0f * v2;
I successfully implemented the first one by overloading the * operator. I'm not sure how to go about the second one though. I know I need to overload the * operator again, but I don't think it should be inside of my vector class. I was absent from class the day my professor explained it, and when I talked to him afterwards he mentioned that it needs to be outside of the class. The problem is that I have no idea how that will work. Any guidance would be great!
EDIT-
#Fede_Reghe That makes sense to me, but when I added it I am now getting this error from the compiler:
Vector.h:64: error: passing ‘const Vector’ as ‘this’ argument of ‘float Vector::operator’ discards qualifiers
In the header, I have these two lines that refer to the * overloads.
Vector operator * (float);
friend Vector operator*(float, const Vector&);
Then I overloaded the [] so that it returns a float of the x, y, or z value. That looks like this in the header:
float operator [] (int);
Outside of the class, I defined the friend * overload like this:
Vector operator * (float f,const Vector& v2)
{
float newX = v2[0] * f;
float newY = v2[1] * f;
float newZ = v2[2] * f;
Vector newVector(newX, newY, newZ);
return newVector;
}
I don't fully understand what the error message means.
You should overload operator outside class and declare it as friend of the class.
For example:
class Vector {
// ...
friend Vector operator*(float, Vector);
};
Vector operator*(float num1, Vector num2)
{
// ...
}
You need the two-argument implementation of operator *(). Here is an example of doing so with operator +() that you can generalize.

c++: overloading + operator for a sparse matrix

void add(sparseMatrix<T> &b, sparseMatrix<T> &c); // c is output
sparseMatrix<T> operator+(sparseMatrix<T> &b);
I'm creating a sparse matrix which is made up of an arrayList of singly linked lists of matrix terms (matrix terms contain the row, column, and value). I'm having trouble overloading the + operator. I have an add method which works fine, but when I try to use it to overload the + operator I get the following errors:
sparseMatrix.cpp: In function ‘int main()’:
sparseMatrix.cpp:268: error: no match for ‘operator=’ in ‘c = sparseMatrix<T>::operator+(sparseMatrix<T>&) [with T = int](((sparseMatrix<int>&)(& b)))’
sparseMatrix.cpp:174: note: candidates are: sparseMatrix<T>& sparseMatrix<T>::operator=(sparseMatrix<T>&) [with T = int]
make: *** [sparseMatrix] Error 1
Here is my implementation for the overloaded + operator:
sparseMatrix<T> sparseMatrix<T>::operator+(sparseMatrix<T> &b)
{
sparseMatrix<T> c;
add(b, c);
return c;
}
The line in main that gives the error is c = a + b (a, b, c are all sparse matrices). Note that if I do a.add(b,c) everything works fine. I have also overloaded the = operator which works when I do a = b etc. but it seems to be complaining about it in the error message I posted. I'm really not sure what the problem is. Any ideas?
note: candidates are: sparseMatrix& sparseMatrix::operator=(sparseMatrix&)
Your operator= should take a const reference.
If the reference isn't const, it can't be bound to a temporary, so the assignment operator can't be used for the temporary created by a + b.
(The same is true for operator+, here also the argument should be const sparseMatrix<T> &. Additionally this method should be declared as const, since it doesn't modify the object it is called on.)
sth: has correctly diagnosed the problem:
But I would make your operators more standard.
class sparseMatrix
{
sparseMatrix(sparseMatrix const& copy);
sparseMatrix& operator=(sparseMatrix const& copy);
sparseMatrix& add(sparseMatrix const& value) // Add value to the current matrix
{
// Do Work.
return *this;
}
// Re-use add to implement the += operator.
sparseMatrix& operator+=(sparseMatrix const& rhs)
{
return add(rhs);
}
// Two things here:
//
// Implement the operator + in terms of the operator +=
//
// This basically means that you make a copy of one parameter then add the other
// value two it. Because + is symmetric it does not matter which you copy and which
// you add to the copy.
//
// So we pass the parameter by value this will provide an implicit copy
// generated by the compiler. This will also help the compiler with NRVO
// Then we just add (*this) to the copy of the rhs.
sparseMatrix operator+(sparseMatrix rhs)
{
return rhs += *this;
}
}