class Currency
{
public:
explicit Currency(unsigned int value);
// method form of operator+=
Currency &operator +=(const Currency &other); // understood!
...
};
The following code shows an equivalent API using a free function version of the operator:
class Currency
{
public:
explicit Currency(unsigned int value);
...
};
// free function form of operator+=
Currency &operator +=(Currency &lhs, const Currency &rhs); // ???
Question1> Why should the free function return Currency& instead of Currency?
Is this a good practice?
Question2> In the implementation, which variable should be used to return, lhs or rhs?
The standard behavior of operator+= is to increment the lhs by the rhs and return a reference to the lhs.
In the member function, the lhs is the calling object, and accordingly, it should return a reference to itself. You seem to expect the free function to behave differently than the member function. Why?
Question 1: the "free function" is not able to access private member variables of the Currency class. If you need to use these variables to perform the += operation, then you should make the operator a member of the class, or make the non-member operator a friend of the class (see example below). Other than that, they're pretty similar.
Question 2: Return lhs. That allows you to chain together calls, such as a += b += c.
class Currency
{
friend Currency& operator+=(Currency &lhs, const Currency &rhs);
};
Currency& operator+=(Currency &lhs, const Currency &rhs)
{
}
Is the same as
class Currency
{
public:
friend Currency& operator+=(Currency &lhs, const Currency &rhs)
{
}
};
Regarding 1st question. You actually can return object by value. But you should always prefer returning by reference (or pointer) to returning by value. Because returning by value involves copy ctor call. It decreases performance. In case above you definitely can return reference, so do it :)
Look to Scott Meyers book "Effective C++". Item 23: Don't try to return a reference when you must return an object. For more details.
This is OK and good for operators that return the lhs bit - i.e. give the compiler a hint that it does not need to create a new object. But operators like +, -, *, etc this would not be true as the returned value
Related
I'm wondering why the () operator override can't be "friend" (and so it needs a "this" additional parameter) while the + operator needs to be friend like in the following example:
class fnobj
{
int operator()(int i);
friend int operator+(fnobj& e);
};
int fnobj::operator()(int i)
{
}
int operator+(fnobj& e)
{
}
I understood that the + operator needs to be friend to avoid the "additional" extra this parameter, but why is that the operator() doesn't need it?
You have overloaded the unary plus operator. And you probably didn't want to do that. It does not add two objects, it describes how to interpret a single object when a + appears before it, the same as int x = +10 would be interpreted. (It's interpreted the same as int x = 10)
For the addition operator, it is not correct that "the + operator needs to be friend".
Here are two ways to add two fnobj objects:
int operator+(fnobj& e);
friend int operator+(fnobj& left, fnobj& right);
In the first form, this is presumed to be the object to the left of the +. So both forms effectively take two parameters.
So to answer your question, instead of thinking that "operator() doesn't need friend", consider it as "operator() requires this" Or better still, "Treating an object as a function requires an object".
You didn't understand this correctly (and aren't using it correctly as well).
There are two ways in C++ to define a binary operator for a class, either as a member function
class A
{
public:
int operator+ (A const& other);
};
or as a free function
class A {};
int operator+ (A const& lhs, A const& rhs);
What you are currently mixing up is that you can declare and define this free function in the class scope as friend, which will allow the function to use private members of the class (which is not allowed in general for free functions).
I am busy doing an assignment for a Comp Sci module in C++ and I am just a bit confused by one of the questions. It asks to give 3 implementations of an overloaded increment operator:
Using the member function Adjust() which was coded in a previous question.
Implementing the overloaded operator as a friend function.
Implementing the overloaded operator as a member function.
Now I understand the concept of overloading the operators I think, that's okay. But I'm actually not too sure about the first one, using the existing member function Adjust(). Because surely if I'm overloading and just calling another function it will either be a friend or a member function calling another member function, if you know what I mean. Anyway, any help would be greatly appreciated. Below is my code for number 2 and 3 just for reference.
//Friend Function
friend Chequebook operator ++(const Chequebook &c); //Declaration in class.
Chequebook operator++(const Chequebook &c) //Function
{
return Chequebook(c.Balance+100);
}
//Member Function
Chequebook operator++(); //Declaration in class.
Chequebook Chequebook::operator++() //Function.
{
return Chequebook(Balance+100);
}
Sorry for the errors in the code. This is supposed to be a pre-increment operator overload.
You probably misunderstand what increment operator does or you did not post full text of homework.
It modifies the object. It can be member and nonmember. It can be prefix and postfix. Here are the examples of how prefix (++x) increment is usually implemented:
class X
{
int i;
public:
// member prefix ++x
X& operator++() { ++i; return *this;}
};
class Y
{
int i;
public:
void adjust() {++i;}
};
// non-member prefix ++y
Y& operator++(Y& y) { y.adjust(); return y;}
class Z
{
int i;
public:
// friend prefix ++z
friend Z& operator++(Z& z) { z.i++; return z;}
};
The postfix increment (x++) is different, should have additional int parameter.
I interpret the first question as "implement the operator++ in terms of the member function Adjust which was coded previously".
Adjust is likely to be a public function so there's no need for a member implementation of operator++. You'd implement it as
Chequebook& operator++(Chequebook& i_lhs)
{
i_lhs.Adjust(1); // Or whatever Adjust actually takes as parameters.
return i_lhs;
}
Well, your #2 attempt is clearly broken, because you have not actually changed the object at all and this is not the semantics of ++, either pre or post. In addition, you appear to be subtracting from the balance to increment?
I have two questions about overloading.
1- Why sometimes do make overloading operators non-member functions?
friend Class operator-(const Class &rhs);
2- What's the difference between
Class operator+(const Class &c1, const Class &c2);
and
Class operator+(const Class &rhs);
if I want to add two objects C3 = C1 + C2?
Any help is appreciated...
If you overload a binary operator as a member function, it ends up asymmetrical: the left operand must be the exact type for which the operator is overloaded, but the right operand can be anything that can be converted to the correct type.
If you overload the operator with a non-member function, then both operands can be converted to get the correct type.
What you have as your second point looks like a concrete example of the same point, not really anything separate at all. Here's a concrete example of what I'm talking about:
class Integer {
int val;
public:
Integer(int i) : val(i) {}
operator int() { return val; }
// Integer operator+(Integer const &other) const { return Integer(val + other.val); }
friend Integer operator+(Integer const &a, Integer const &b) {
return Integer(a.val + b.val);
}
};
int main() {
Integer x(1);
Integer y = x + 2; // works with either operator overload because x is already an Integer
Integer z = 2 + x; // works with global overload, but not member overload because 2 isn't an Integer, but can be converted to an Integer.
return 0;
}
Also note that even though the definition of the friend function is inside the class definition for Integer, the fact that it's declared as a friend means it's not a member function -- declaring it as friend makes it a global function, not a member.
Bottom line: such overloads should usually be done as free functions, not member functions. Providing the user with an operator that works correctly (drastically) outweighs theoretical considerations like "more object oriented". When necessary, such as when the implementation of the operator needs to be virtual, you can do a two-step version, where you provide a (possibly virtual) member function that does the real work, but the overload itself is a free function that invokes that member function on its left operand. One fairly common example of this is overloading operator<< for a hierarchy:
class base {
int x;
public:
std::ostream &write(std::ostream &os) const {
return os << x;
}
};
class derived : public base {
int y;
public:
std::ostream &write(std::ostream &os) const {
return (base::write(os) << y);
}
};
std::ostream &operator<<(std::ostream &os, base const &b) {
return b.write(os);
}
This supports both polymorphic implementation (and access to a base class' protected members, if necessary) without giving up the normal characteristics of the operator to get it.
The primary exceptions to overloading binary operators as free functions are assignment operators (operator=, operator+=, operator-=, operator*= and so on). A conversion would produce a temporary object, which you can't assign to anyway, so for this particular case, the overload should be (must be, as a matter of fact) a member function instead.
1-Why sometimes do make overloading operators non-member functions?
It's matter of choice. You can either make the operator +/- a class member or make it a free friend function.
The syntax you provided for operator - is wrong if it's a free friend function, it should take 2 arguments (similar to operator + in your example).
2- What's the difference between
As said before, it's just a syntax different. The first one should be a free friend function and the second one is a class member.
On top of that, I believe keeping an operator as class member method is superior compared to free function because:
Member method can access the protected members of base class if
applicable, but the friend function cannot
Member method is more object oriented approach because you associate a method which relates to a class
Making the overloaded operator a friend is a better option because take this example
class Comples
{
public:
Complex(float real, float imaginary);
friend operator+ (const Complex &rhs);
...
};
By having the operator a friend you can do the following
Complex result1 = 5.0 + Comples(3.0, 2.0);
and
Complex result1 = Comples(3.0, 2.0) + 5.0;
Which obeys the rules of additions communitivity property. This cannot be achieved if the overloaded operator is a member function. This is due to the compiler able to implicitly create a Complex object asrequired in this case. Thus the addition operator when being a friend acts in accordance with the normal notion of addition in mathematics.
I feel I have a bit of a hole in my understanding of the friend keyword.
I have a class, presentation. I use it in my code for two variables, present1 and present2, which I compare with ==:
if(present1==present2)
Here's how I defined the operator == (in class presentation):
bool operator==(const presentation& p) const;
However, I was told that using friend and defining it outside of the class is better:
friend bool operator==(presentation&, presentation&);
Why? What's the difference between the two?
Your solution works, but it's less powerful than the friend approach.
When a class declares a function or another class as friend it means that friend function or class have access to the declaring class' privates and protected members. It's as if the declared entity was a member of the declaring class.
If you define operator==() as a member function then just like with the friend case the member function has full access to the class' members. But because it is a member function it specifies a single parameter, as the first parameter is implied to be this: an object of type presentation (or a descendent thereof). If, however, you define the function as a non-member then you can specify both parameters, and this will give you the flexibility of comparing any two types that can cast into a presentation using that same function.
For example:
class presentation {
friend bool operator==(const presentation&, const presentation&);
// ...
};
class Foo : public presentation { /* ... */ };
class Bar : public presentation { /* ... */ };
bool operator==(const presentation& p1, const presentation& p2)
{
// ...
}
bool func(const Foo& f, const Bar& b, const presentation& p)
{
return f == b || f == p );
}
Lastly, this raises the question "why the friend declaration?". If the operator==() function does not need access to private members of presentation then indeed the best solution is to make it a non-member, non-friend function. In other words, don't give a function access privileges which is doesn't need.
In the first case, your function operator== is a nonstatic class member. It has therefore access to private and protected member variables.
In the second case, the operator is externally declared, therefore it should be defined as a friend of the class to access those member variables.
An operator implemented as a method, can only be called, if the left hand side expression is a variable (or a reference to the object) of the class, the operator is defined for.
In case of an operator== usually you are interested in comparing two objects of the same class. Implementation, as a method solves your problem here.
Imagine however, that you write a string class and you want an operator, to work in this scenario:
const char *s1 = ...
MyString s2 = ...
if(s1 == s2){...
To make the expression s1 == s2 legal, you have to define an opetator== as a function external to MyString class.
bool operator==(const char *, const MyString&);
If the operator needs an access to the private members if your class, it has to be a friend of your class.
In case of operators << and >>, that work on streams, you define an operator, whose left operand is a stream instance and the right one is your class, so they can't be methods of your class. Like in the example above, they have to be functions external to your class and friends, if the access to private members is required.
I like Benoit's answer (but I can't vote it up), but I figure an example wouldn't hurt to clarify it. Here's some Money code I have (assume everything else is placed right):
// header file
friend bool operator ==(const Money, const Money); // are the two equal?
// source file
bool operator ==(const Money a1, const Money a2)
{
return a1.all_cents == a2.all_cents;
}
Hope that helps.
Take a look at this sorta duplicate here: should-operator-be-implemented-as-a-friend-or-as-a-member-function
What is important to point out, this linked question is about << and >> which should be implemented as friends since the two operand are different types.
In your case it makes sense to implement it as part of the class. The friend technique is used (and useful) for cases where more than one type is used and often does not apply to == and !=.
I have a vector of Student objects which I want to sort using #include <algorithm> and sort(list.begin(), list.end());
In order to do this, I understand that I need to overload the "<" operator but after trying (and failing) with several methods suggested online, I am running out of ideas.
Here is my latest attempt:
In Student.h...
...
using namespace std;
class Student
{
friend bool operator <(const Student& first, const Student& second);
public:
...
private:
...
};
And in Student.cpp...
...
#include "Student.h"
using namespace std;
...
bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
where "Name()" is a constant function which returns a string.
The program compiles and runs, but my operator function is never called during the sort and when I tried comparing two Student objects like s1 < s2 I got an "error: overloaded operator not found"
How can I correctly overload this operator so that my sort will work as I intend?
You didn't say which compiler you were using, but I suspect you're using a fairly recent one that implements the "friend is not a declaration" rule. The friend statement inside the class doesn't serve as a function declaration; other modules that include Student.h don't see any declaration of the function. It's visible only inside the Student.cpp file. (Older compilers don't have this rule, and treat a friend declaration as a function declaration.)
The function doesn't need to be a friend, since it doesn't use any private members of the Student class (I'm assuming Name() is public). Move the function declaration outside the class, and replace "friend" with "extern", and it should work.
It is possible to make the operator a member function, as some posters above suggested, but it isn't necessary. Making comparison operators member functions is generally frowned upon, because it means that the two arguments aren't treated symmetrically (one is the invisible "this" argument, the other is a normal function argument), which can lead to surprising results in some cases (for example, different type conversions may be applied to the arguments).
I wouldn't use a friend here, and I'm not sure it works at all. What I would use is...
class Student
{
public:
bool operator< (const Student& second) const;
};
bool Student::operator< (const Student& second) const
{
return (Name() < second.Name());
}
Note the trailing const, indicating that within operator<, *this is constant.
EDIT I cannot delete this answer because it was accepted, but I would if I could. I also can't replace it with a correct one. See Drew Dormanns comment below, and Ross Smiths answer.
By the way, with a function this simple I would personally just do this, unless the style guide bans the definition of functions inside class definitions:
class Student
{
friend bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
...
};
This form of the "friend" declaration lets you define a non-member operator< inside the body of the class. It's still a friend, so Name() can be private if desired.
Well, you could do it as an internal operator:
class Student
{
public:
bool operator <(const Student& second) const;
...
private:
...
};
With an implementation comparing 'this' to second. The question in my mind is: Does the 'Name' method come in a const flavor? Because if it doesn't, then you can't write a const method that uses it.