If I have an operator overload on my class, is the assignment version of the operator implicitly created as well?
class square{
square operator+(const square& B);
void operator=(const square& B);
};
As in, can I then call
square A, B;
A += B;
with the compiler implicitly deciding to call operator+ then operator=?
No, += must be defined explicitly.
As a side note, operator+ should usually create a new object:
square operator+(const square& B);
And operator= should return a reference to *this:
square& operator=(const square& B);
Also worth noting that operator+ is usually implemented in terms of operator+=, i.e. operator+ calls operator+= on the new copy.
No, the operators aren't implicitly defined. However, boost/operators.hpp defines useful helper templates to avoid boiler-plate code. Example from their docs :
If, for example, you declare a class like this:
class MyInt
: boost::operators<MyInt> {
bool operator<(const MyInt& x) const;
bool operator==(const MyInt& x) const;
MyInt& operator+=(const MyInt& x);
MyInt& operator-=(const MyInt& x);
MyInt& operator*=(const MyInt& x);
MyInt& operator/=(const MyInt& x);
MyInt& operator%=(const MyInt& x);
MyInt& operator|=(const MyInt& x);
MyInt& operator&=(const MyInt& x);
MyInt& operator^=(const MyInt& x);
MyInt& operator++();
MyInt& operator--(); };
then the operators<> template adds more than a dozen additional operators, such as operator>, <=, >=, and
(binary) +. Two-argument forms of the templates are also provided to
allow interaction with other types.
In addition, there is also support for implicitly "deducing" just a specific set of operators using arithmetic operator templates.
No operator+= is its own operator and must be defined explicitly.
Note that operator+ should return a new object rather than a reference to the original object. The original object should be left unchanged.
operator+= should return the original object with the required value added. operator+= is often preferable as it eliminates a temporary object.
Related
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)
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;
I'm implementing a c++-class representing a fraction. Here goes my code.
class Fraction
{
public:
Fraction(char i);
Fraction(int i);
Fraction(short i);
Fraction(long int l);
#ifdef __LP64__
Fraction(long long l);
#endif
Fraction(float f);
Fraction(double d);
Fraction(double x, double y);
Fraction operator +() const;
Fraction operator -() const;
Fraction& operator +=(const Fraction& other);
Fraction& operator -=(const Fraction& other);
Fraction& operator *=(const Fraction& other);
Fraction& operator /=(const Fraction& other);
bool operator ==(const Fraction& other);
bool operator !=(const Fraction& other);
bool operator >(const Fraction& other);
bool operator <(const Fraction& other);
bool operator >=(const Fraction& other);
bool operator <=(const Fraction& other);
operator double();
operator float();
static void commonize(Fraction& a, Fraction& b);
void shorten();
double getNumerator();
double getDenominator();
friend Fraction operator +(Fraction const& a, Fraction const& b);
friend Fraction operator -(Fraction const& a, Fraction const& b);
friend Fraction operator *(Fraction const& a, Fraction const& b);
friend Fraction operator /(Fraction const& a, Fraction const& b);
friend ostream& operator <<( ostream& o, const Fraction f);
protected:
double numerator, denominator;
};
I now have two little problems.
Now trying to call
Fraction a(1, 2);
cout << (3 + a) << endl;
simply results in this error:
fractiontest.cpp:26: error: ambiguous overload for ‘operator+’ in ‘3 + a’
fractiontest.cpp:26: note: candidates are: operator+(int, double) <built-in>
fractiontest.cpp:26: note: operator+(int, float) <built-in>
All I'd really want is this:
explicit operator double();
explicit operator float();
But apparently, this doesn't work. I'd like these two cast-operators to be called iff I use the cast notation. For example Fraction f(1, 2); double d = (double)(f);
By definition the conversion operators are implicit. You can't make them explicit.
The normal solution is named member functions to do the conversion. I think you could also create a specialized template method that would look just like a static_cast and call through to the explicit class method.
Remove the conversion operators and 3 + a should use your friend operator+ while implicitly converting 3 to Fraction via the implicit constructor Fraction(int i);.
Edit: On the case of the explicit conversion operators, C++0x specifically allows this:
12.3.2 [class.conv.fct] p2
A conversion function may be explicit, in which case it is only considered as a user-defined conversion for direct-initialization.
The C++03 standard doesn't specifically mention this.
We can overload assignment operator as a normal function, but we cannot overload assignment operator as a friend function. Why?
Because the C++ Standard says so, Article 13.5.3/1:
An assignment operator shall be
implemented by a non-static member
function with exactly one parameter.
Because a copy assignment operator
operator= is implicitly declared for a
class if not declared by the user
(12.8), a base class assignment
operator is always hidden by the copy
assignment operator of the derived
class.
That's all you really need to know. A friend function is not a member function, so it cannot be used to overload the assignment operator.
If you would like to write:
MyClassObject = MyFriendObject;
Then you would want to implement a constructor that takes a const reference to the friend class as it's parameter.
The difference between overloading by friend function and overloading by member function is that the calling object must be the first operand in overloading by member function, while there is no restriction in overloading by friend function. This is the reason behind the standard. Similarly, some other operators requiring the first operand to be the calling function must be overloaded using member functions (examples: =, [], ->, and ( )).
You cannot "extend" the assignment operator with a "free function" outside the class, but you can design the class so it will allow it:
Data.h
class Data {
public:
Data& operator=(const Data& lhs) { /*...*/; return *this; }
template <typename T> Data& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
private:
// ...
};
Point.h
class Point {
public:
float x,y;
Point& operator=(const Point& lhs) { x = lhs.x, y = lhs.y; return *this; }
template <typename T> Point& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
};
Assignment.h
Data& assign(const Data& lhs, const Point& rhs) {
lhs["x"] = rhs.x;
lhs["y"] = rhs.y;
return lhs;
}
Point& assign(const Point& lhs, const Data& rhs) {
rhs.query("x", lhs.x) || rhs.query(0, lhs.x);
rhs.query("y", lhs.y) || rhs.query(1, lhs.y);
return lhs;
}
Consider the following code:
class A
{
public:
A& operator=( const A& );
const A& operator+( const A& );
const A& operator+( int m );
};
int main()
{
A a;
a = ( a + a ) + 5; // error: binary '+' : no operator found which takes a left-hand operand of type 'const A'
}
Can anyone explain why the above is returned as an error?
"( a + a )" calls "const A& operator+( const A& )" and returns a constant reference which is then passed to "const A& operator+( int m )" if I'm not mistaken.
How can one fix the above error (without creating a global binary operator+ or a constructor that accepts an int) such that the statement inside main() is allowed?
which is then passed to "const A& operator+( int m )" if I'm not mistaken
No. Since the LHS is a const A& and RHS is an int, it will call*
[anyType] operator+ (int rhs) const
// ^^^^^ note the const here.
as you've only provided the non-const version const A& operator+( int m ), the compiler will complain.
*: Or operator+(const int& rhs) const or operator+(float rhs) const... The crucial point is that it must be a const method.
operator+ should return an instance, not a reference:
// as member function
A operator+(const A& other);
// as free function
A operator+(const A& left, const A& right);
To explain the specific problem is "returns a constant reference which is then passed to const A& operator+( int m )". Since you have a const reference, it cannot call that function because it's not a const method (i.e. const A& operator+( int m ) const).
That said, that is not the way to fix operator+. If you're returning a reference, what is it a reference to? A local in operator+ would be bad as you shouldn't return a reference to a local. A reference to a global would be bad because it will limit how your code can be used properly. A reference to allocated memory would be bad because it will leak memory. A reference to *this would be bad because then operator+ is acting like operator +=.
Because you are modifying the left-hand side object when adding. You can't do that with a const object. Take Samuel advice btw, because the idiomatic way is to return a new copy of the added objects.
The function needs to be const:
const A& operator+( int m ) const;
As const A& operator+( const A& ) returns a const reference a non-const member function const A& operator+( int m ) can not be called over a const object.
Either, the first operator should be defined as A& operator+( const A& ) or, the second operator as const A& operator+( int m )const;
However, these changes will only make them technically correct, not aesthetically in majority of the cases, as a binary operator is not supposed to modify any of the input argument and yet to compute a result and return. Thus the result have to be returned by value or in case of C++0x , as a r-value reference.
i.e A operator+(const A& rhs)const or A&& operator+(const A& rhs)const;
The problem is that (a+a) returns a so-called rvalue (basically a fancy term for a temporary). While you can invoke member functions on an rvalue, you can only invoke const member functions. Also, everyone is right in saying that operator+ must alwasys return a new value.
Your operators should be implemented like this:
A operator+( const A& ) const;
A operator+( int m ) const;
However, binary operators which don't modify their left argument are probably better implemented as free functions:
class A { ... };
A operator+(const A& lhs, const A& rhs);
A operator+(const A& lhs, int rhs);
Usually, they are implemented on top of operator+=, which is implemented as a member:
class A {
public:
A& operator+=(const A& rhs);
A& operator+=(int rhs);
};
inline A operator+(A lhs, const A& rhs) // note: lhs is passed by copy now
{
lhs += rhs;
return lhs;
}
A operator+(A lhs, int rhs) // note: lhs is passed by copy now
{
lhs += rhs;
return lhs;
}