I read that implementing operators as friend function will be better. How to overload += operator as a friend function when I already have + operator function:
friend Dollar operator+(const Dollar &p1, const Dollar &p2);
friend Dollar &operator+=(const Dollar &p1, const Dollar &p2);
This is wrong since I need to return a reference to a variable.
Dollar &operator+=(const Dollar &p1, const Dollar &p2)
{
return p1+p2;
}
Overloading operators as friend functions is better in order to allow conversions to apply to both the left and right side of the expression. For example, string's operator+ is a friend so that I can write "Hello " + string("World") rather than only being able to write string("Hello ") + "World".
However, this reasoning doesn't apply to mutators such as operator+=. You have to take a non-const left argument, which precludes being able to use this operator on a temporary. For this reason, it's recommended to implement non-mutating operators as friend (or otherwise free-) functions and mutators as member functions. (In fact, operator= can only be overloaded as a member function.)
You also need to modify the lvalue.
Dollar &operator+=(Dollar &p1, const Dollar &p2)
{
p1=p1+p2;
return p1;
}
The usual approach is to provide += as a member function that modifies *this and to implement + as a free function that uses +=.
Related
I Have a Fraction Class.
I need to do 3 operations on Fraction Object i.e
Multiply two Fraction objects. e.g F1*F2
Multiply a Fraction object by an integer. For ex. F1*3
Multiply an integer by a Fraction object. For ex. 3*F1.
The first two case can be achieved by overriding the Fraction Class * operator.
Fraction operator*(const Fraction&);
Fraction operator*(const int&);
but how to multiply an integer by a fraction Object? The third case
Any Suggestions??
PS: I don't want to treat integer as a Fraction object e.g (3/1) and then doing the multiplication.
You need to implement the operator overload as a free function, like this:
Fraction operator *(int lhs, Fraction rhs)
{
rhs *= lhs;
return rhs;
}
Note that I have implemented the function in terms of Fraction::operator*=(int) (see here why this is considered good practice). If this function is not present, you might want to pass the second parameter as const Fraction& rhs and provide a different implementation.
Besides, note that an idiomatic way to handle this scenario is to allow an implicit construction of Fraction instances by a single int argument, so your constraint seems a bit awkward to me. Further note that users of your Fraction class might expect all arithmetic operations to be possible (why should there be operator*, but not operator/?). To reduce the amount of manual code to be written in such cases, the boost operator library can be of great help.
Can I make a case for the inplace friend function?
In c++11 you can declare and write your friend function inside the class, which can make it much neater:
class MyNumber
{
private:
Clever c;
Clever Multiply (Clever, i) { ... }
public:
MyNumber operator * (int i)const { return Multiply(c,i) }
MyNumber operator * (const MyNumber &i)const { ... }
const MyNumber& operator *= (int i) { return c= Multiply(c, i); }
// introducing the inline friend (presuming multiply is commutative/symmetric here)
friend MyNumber operator (int i, const MyNumber& j) { return j.Multiply(c,i); }
};
Note that this friend function is still actually a global function, and has access to the class internals, but its implementation is now tidily inside the class definition.
The neatness of this style is such that I am tempted to use it even when I don't actually need the dirty friend access.
With these math overloading objects, also consider the RValue substitution overloads. An rvalue implementation of binary multiply implemented as mult-assign can show some efficiencies, though perhaps not soo much with only a 2-value fraction class.
There are three different ways to overload operators: the member function way, the friend function way, and the normal function way.
In this specific case we need overload the operators in friend function way.
friend Fraction operator*(const Fraction &a, const Fraction &b); //F1*F2
friend Fraction operator*(const Fraction &a, int b); //F1*3
friend Fraction operator*(int a, const Fraction &b); //3*F1
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.
I have got a question about unary operator overloading. The code is as follows:
class Fraction {
public:
Fraction() {}
Fraction(int a);
Fraction(int n, int d, int reduce=1);
Fraction operator +(const Fraction& y) const;
Fraction operator -(const Fraction& y) const;
Fraction operator -() const; // unary negation
// etc.
};
for unary operator-, the code is as follows:
Fraction Fraction::operator -() const { return (Fraction(-num, denom, 0)); }
Suppse we have three Fraction objects, f1,f2 and f3.
I know for code:
f3=f1+f2 is equal to f3=f1.operator+(f2), that is the object in front of the operator will call the operator and the one behind will be passed as parameter, right?
Then, for unary operator -, the code is
f3=-f1
following the thought above for operator +, I think the code should be like f3=f1-, which is equal to f3=f1.operator-(). Why the actual code is f3=-f1 instead of f3=f1-? I think the object in front of the operator should call it... I know in math, it is f3=-f1, but how can the compiler recognize the code f3=-f1 which actually is that f1 calls the operator? how does it know that in this case, - is an unary operator?
Thanks so much!
There are only two unary operators in which the reference to the object comes first. That's postfix ++ and postfix --.
The syntax for how to distinguish these in your overloads is a little bit odd. You add a fake argument:
class Ptr_to_X {
// ...
X operator++(); //prefix: no argument
X& operator++(int); //postfix: because of
//the argument
X operator--(); //prefix: no argument
X& operator--(int); //postfix: because of
//the argument
};
Here's some history of how that came to be. Make of it what you will.
Other than the postfix forms of those, all the other unary operators appear before the object reference. That covers:
Unary minus (-)
Unary plus (+)
Ones complement (~)
Address of (&)
Pointer dereference (*)
Logical NOT (! or not)
If it makes you uncomfortable because you are used to seeing "the method" always appearing "after the object"...that's too bad. Some languages have syntax which is regimented and regular...using all prefix or all postfix notation, for instance. But cognitive scientists and linguists believe there are arguments that the human mind operates on a kind of language instinct, and I'd argue that many of the purely consistent languages battle against our mind's desire to create the structure "in our heads".
Either way, as #dyp says, all these operators came from C (except the ability to write ! as not, which I do, because it's in the standard and is harder to miss). It would be weird if you negated integers with a minus sign in front...and then negated a complex number class with the minus sign in back.
Is it right to define operator += in this way ?!
void operator +=(const BigNumber& other)
{
*this=(*this) + other;
}
In a class like this :
class BigNumber
{
public:
//....
BigNumber operator +(const BigNumber& other)
{
return sum(other);
}
//....
}
Yes. But the right way is to implement operator+ in terms of operator+=:
struct foo
{
int value;
foo& operator+=( const foo& other )
{
value += foo.value;
return *this ;
}
friend foo operator+( foo lhs , const foo& rhs )
{
return lhs += rhs;
}
};
Why?
First of all, the binary operator+() shouldn't be defined as member function instead of free function. This allows you to implement addition where the first parameter is not a foo. The common idiom is to declare it friend inside the class to ride over encapsulation.
Second, this way provides a coherent, maintainible, and efficient interface.
Coherency:
If you implement a += operation, the user spects (Except in rare cases) the type provides a binary addition too. Implementing + with += provides this ensuring that the behavior of the two operations is coherent.
Maintainability:
You have implemented + using +=, so the code which really performs the addition is written only once. If you need to change the operation in the future you have to change one code only, and if it has a bug that bug is in one site only. Reducing code duplication is a good practice in general.
Efficiency:
The way the operator+() is written allows the compiler to easily elide copies, boosting the performance of the binary addition.
The idiom used is "copy first operand, operate on it, return the copy". So the compiler can easily perform a return value optimization (RVO). Also, it passes the first operand by value instead of copying the operand by hand inside the function. This allows the compiler to perform more copy elisions when the first operand is an rvalue (Let the compiler decide when and how to copy).
Yes you can do it your way:
BigNumber& operator +=(const BigNumber& other)
{
*this=(*this) + other;
return *this;
}
The usual approach is the opposite way:
// Note a is no const reference
BigNumber operator + (BigNumber a, const BigNumber& b)
{
return a += b;
}
A reasoning for your approach might be memory allocation.
Is there a canonical or recommended pattern for implementing arithmetic operator overloading in C++ number-like classes?
From the C++ FAQ, we have an exception-safe assignment operator that avoids most problems:
class NumberImpl;
class Number {
NumberImpl *Impl;
...
};
Number& Number::operator=(const Number &rhs)
{
NumberImpl* tmp = new NumberImpl(*rhs.Impl);
delete Impl;
Impl = tmp;
return *this;
}
But for other operators (+, +=, etc..) very little advice is given other than to make them behave like the operators on built-in types.
Is there a standard way of defining these? This is what I've come up with - are there pitfalls I'm not seeing?
// Member operator
Number& Number::operator+= (const Number &rhs)
{
Impl->Value += rhs.Impl->Value; // Obviously this is more complicated
return *this;
}
// Non-member non-friend addition operator
Number operator+(Number lhs, const Number &rhs)
{
return lhs += rhs;
}
In Bjarne Stroustrup's book "The C++ Programming Language", in chapter 11 (the one devoted to Operator Overloading) he goes through witting a class for a complex number type (section 11.3).
One thing I do notice from that section is that he implements mixed type operations... this is probably expected for any numeric class.
In general, what you've got looks good.
The big thing to consider when writing any operator is that member operators do not undergo conversions on the left parameter:
struct example {
example(int);
example operator + (example);
};
void foo() {
example e(3), f(6);
e + 4; // okay: right operand is implicitly converted to example
e + f; // okay: no conversions needed.
6 + e; // BAD: no matching call.
}
This is because conversion never applies to this for member functions, and this extends to operators. If the operator was instead example operator + (example, example) in the global namespace, it would compile (or if pass-by-const-ref was used).
As a result, symmetric operators like + and - are generally implemented as non-members, whereas the compound assignment operators like += and -= are implemented as members (they also change data, meaning they should be members). And, since you want to avoid code duplication, the symmetric operators can be implemented in terms of the compound assignment ones (as in your code example, although convention recommends making the temporary inside the function).
The convention is to write operator+(const T&) and operator-(const T&) in terms of operator+=(const T&) and operator-=(const T&). If it makes sense to add and subtract to/from primitive types then you should write a constructor that constructs the object from the primitive type. Then the overloaded operators will also work for primitive types, because the compiler will call the appropriate constructor implicitly.
As you mentioned yourself, you should avoid giving access privileges to functions that don't need it. But in your code above for operator+(Number, const Number&) I'd personally make both parameters const references and use a temp. I think it isn't surprising the commenter below your question missed this; unless you have a good reason not to, avoid surprises and tricks and be as obvious as possible.
If you want your code to integrate with other numeric types, say std::complex, watch out for cyclic conversions. That is, don't supply operator OtherNumeric() in Numeric if OtherNumeric supplies a constructor that takes a Numeric parameter.
It is traditional to write the operator X in terms of the operator =X
It is also traditional the all parameters to the standard operators are const
// Member operator
// This was OK
Number& Number::operator+= (Number const& rhs)
{
Impl->Value += rhs.Impl->Value; // Obviously this is more complicated
return *this;
}
// Non-member non-friend addition operator
Number operator+(Number const& lhs,Number const& rhs)
{
// This I would set the lhs side to const.
// Make a copy into result.
// Then use += add the rhs
Number result(lhs);
return result += rhs;
}
You mention assignment operator.
But you did not mention the copy constructor. Since your class has ownership of a RAW pointer I would expect you to define this as well. The Assignment operator is then traditionally written in terms of the copy constructor.