Consistency in placing operator functions - c++

I have a class like this:
class A {
...private functions, variables, etc...
public:
...some public functions and variables...
A operator * (double);
A operator / (double);
A operator * (A);
...and lots of other operators
}
However, I want to also be able to do stuff like 2 * A instead of only being allowed to do A * 2, and so I would need functions like these outside of the class:
A operator * (double, A);
A operator / (double, A);
...etc...
Should I put all these operators outside of the class for consistency, or should I keep half inside and half outside?

IMHO, the concern shouldn't be with stylistic consistency, but with encapsulation consistency; generally if a function does not need access to private members, it should not be part of the class. This is not a hard an fast rule, see arguments for it here.
So if your operators do not require private access, put them all outside. Otherwise, they will all have to be inside like so:
class A {
...
public:
...
A operator * (double);
A operator / (double);
friend A operator * (double, A);
friend A operator / (double, A);
...
};

From your replies to comments in the question it seems that you have an implicit conversion from double to A in your class. something like:
class A
{
// ...
public:
A(double);
// ...
};
In this case you can simply define a free function for each operator of the form:
A operator*( const A&, const A& );
and it will be used if either side is an A object and the other side is implicitly convertible to an A. For this reason it is often preferable to make symmetric binary operators free functions.
Frequently it can be easier to implement binary * in terms of the assignment version *=. In this case I would make the assignment version a member function and define * as something like:
A operator*( const A& l, const A& r )
{
A result(l);
result += r;
return result;
}
Otherwise as operator* is plainly part of your class interface I would have no problem with making it a friend if required.

So what you are saying is that because you must put some operators (the ones that don't have A as the first param) outside the class, maybe you should put them all there so people know where to find them? I don't think so. I expect to find operators inside the class if at all possible. Certainly put the "outside" ones in the same file, that will help. And if the outside ones need access to private member variables, then adding the friend lines is a huge hint to look elsewhere in the file for those operators.
Would I go so far as to include the friend lines even if my implementation of the operators could actually be done with public getters and setters? I think I would. I think of those operators as really being part of the class. It's just that the language syntax requires them to be free functions. So generally I use friend and I write them as though they were member functions, not using getters and setters. It's a pleasant side effect that the resulting need for friend statements will cause them all to be listed in the definition of the class.

Related

Why is it recommended to declare functions as "friends" in operator overloading [duplicate]

This question already has answers here:
Operator overloading : member function vs. non-member function?
(2 answers)
Closed 8 years ago.
I have read this at many places which recommend of using "friend" while overload operators but no body explained it clearly as to why it is really needed? Why can not we declare them as plain member function? Any shortcoming?
Googled this but did not get any clear answer.
Sometimes you can't declare operator overload as a member function, like in IO operator<< and operator>>. The first parameter of these functions has to be ostream or istream, which are library classes and you can't extend them, declaring such functions as friend gives them access to private variables of your class.
Using friend means it's a nonmember friend function.
For improving encapsulation by minimizing dependencies, it's better to declare nonmember nonfriend functions. If it need to access the private/protected member of the class, make it friend. At last, make it a member function.
Here's an algorithm to determine whether a function should be a member and/or friend, from [C++ Coding Standards: 101 Rules, Guidelines, and Best Practices By Herb Sutter, Andrei Alexandrescu](Item 44. Prefer writing nonmember nonfriend functions):
// If you have no choice then you have no choice; make it a member if it must be:
If the function is one of the operators =, ->, [], or (), which must be members:
Make it a member.
// If it can be a nonmember nonfriend, or benefits from being a nonmember friend, do it:
Else if: a) the function needs a different type as its left-hand argument (as do operators >> or <<, for example); or b) it needs type conversions on its leftmost argument; or c) it can be implemented using the class's public interface alone:
Make it a nonmember (and friend if needed in cases a) and b) ).
If it needs to behave virtually:
Add a virtual member function to provide the virtual behavior, and implement the nonmember in terms of that.
Else: Make it a member.
In some case, such as above-mentioned a) and b), you can't achieve them by member function, you have to declare them as nonmember function, and make them friend if need to access the private/protected member of the class.
There are a few reasons people use friend:
sometimes granting friendship is actually reasonable, as the public API shouldn't expose some members than need to be compared
it's convenient for a lazy programmer to grant access to all the private and protected data members, ensuring you can write the operator implementation without needing to go back to grant access later or use a less obvious/direct public function (that's NOT a good reason, just a lazy one)
you can define the operator function inside the class, where any template parameters, typedefs, constants etc. don't need to be explicitly qualified as they would in the surrounding [namespace] scope. That's considerably simpler for those new to C++.
e.g.:
template <typename T>
struct X
{
friend bool operator==(const X& lhs, const X& rhs) { ... }
};
...vs...
...struct X as above without ==...
template <typename T>
bool operator==(const X<T>& lhs, const X<T>& rhs) { ... }
in a two-birds-with-one-stone scoop, it makes the function nominally inline, avoiding One Definition Rule complications
Only the first reason above is a compelling functional reason for making the operator a friend, rather than making it a non-member function, given the lesser encapsulation and correspondingly higher maintenance burden involved.
There are excellent reasons though to prefer either a friend or non-friend non-member function to a member function, as an implicit constructor can then kick in to allow the operator to work with one instance of the class and another value from which a second instance can be constructed:
struct X { X(int); };
bool operator==(const X& lhs, const X& rhs);
x == 3; // ok for member or non-member operator==
3 == x; // only works for non-member operator== after implicit X(3) for lhs
You are listing two options only for overloaded operator, while actually there are three:
global function, not friend
member function
global function, friend of the class
You did not list the first one, and yet it is the recommended one. If you can define an operator in terms of existing class public interface, define it as global function outside the class. In this way you do not extend the class public interface without need, minimizing the number of functions with access to the class private members.
What to do if the operator needs to access the class private members? Then you have two options - member function or a friend global function. From those two member function is preferable because it is cleaner. However, in some cases it is not possible to define an overloaded operator as the member function. If the object of your class is right-hand argument to two-argument operator, then global function is the only choice.
I assume that we are comparing global-scope friends that are defined in class and non-friends.
The reasons that the former is sometimes preferred are that such functions...
... need access to the data members for the operation to be performed. This can also be done by loosening encapsulation by providing the data through public getters, but that's not always desired.
... shall only be found via ADL to avoid pollution of some namespaces and overload candidate sets. (Only friend functions that are defined in the class they are a friend of satisfy this!)
Moreover, a minor goodie is that for class templates, it's easier to define a global function that operates on specializations inside them since we avoid making the function a template. Also the function is implicitly inline. All this shortens the code, but is no primary reason.
If your implementation followed proper data encapsulation then you might not exposed your data variables to outside world and all data members will be declared as private.
But using operator overloading most of the times you will be accessing the data members , please note it here you will be accessing the data members outside your class. So to provide access to the data members outside your class it is advised to declare the operator overloaded function as friend.
But this might not be required for unary operators , as it will operate on the data members of the particular class in which it is called.
Let me know if you need any examples for your understanding.
There are serious advantages to non-member functions when dealing with operators.
Most operators are binary (take two arguments) and somewhat symmetrical, and with a member operator they only work if *this is the left-hand side argument. So you need to use a non-member operator.
The friend pattern both gives the operator full access to the class (and, operators are usually intimate enough that this isn't harmful), and it makes it invisible outside of ADL. In addition, there are significant advantages if it is a template class.
Invisible outside of ADL lets you do crazy stuff like this:
struct bob {
template<class Lhs, class Rhs>
friend bob operator+( Lhs&&, Rhs&& ) { /* implementation */ }
}
here our operator+ is a template that seemingly matches anything. Except because it can only be found via ADL on bob, it will only be matched if it is used on at least one bob object. This technique can let you pick up on rvalue/lvalue overloads, do SFINAE testing on properties of types, etc.
Another advantage with template types is that the operator ends up not being a template function. look here:
template<class T>
struct X {};
template<class T>
bool operator==( X<T>, X<T> ) { return true; }
template<class T>
struct Y {
friend bool operator==( Y, Y ) { return true; }
};
struct A {
template<class T>
operator X<T>() const { return {}; }
};
struct B {
template<class T>
operator Y<T>() const { return {}; }
};
int main() {
A a;
X<int> x;
B b;
Y<int> y;
b == y; // <-- works!
a == x; // <-- fails to compile!
}
X<T> has a template operator==, while Y<T> has a friend operator==. The template version must pattern-match both arguments to be a X<T>, or it fails. So when I pass in an X<T> and a type convertible to X<T>, it fails to compile, as pattern matching does not do user defined conversions.
On the other hand, Y<T>'s operator== is not a template function. So when b == y is called, it is found (via ADL on y), then b is tested to see if it can convert to a y (it can be), and the call succeeds.
template operators with pattern matching are fragile. You can see this problem in the standard library in a few points where an operator is overloaded in ways that prevent conversion from working. Had the operator been declared a friend operator instead of a public free template operator, this problem can be avoided.

Which C++ operators can not be overloaded without friend function?

Which C++ operators can not be overloaded at all without friend function?
You only need a friend declaration if:
You define the operator as a standalone function outside the class, and
The implementation needs to use private functions or variables.
Otherwise, you can implement any operator without a friend declaration. To make this a little bit more concrete... one can define various operators both inside and outside of a class*:
// Implementing operator+ inside a class:
class T {
public:
// ...
T operator+(const T& other) const { return add(other); }
// ...
};
// Implementing operator+ outside a class:
class T {
// ...
};
T operator+(const T& a, const T& b) { return a.add(b); }
If, in the example above, the "add" function were private, then there would need to be a friend declaration in the latter example in order for operator+ to use it. However, if "add" is public, then there is no need to use "friend" in that example. Friend is only used when granting access is needed.
*There are cases where an operator cannot be defined inside a class (e.g. if you don't have control over the code of that class, but would still like to provide a definition where that type is on the left-hand side, anyway). In those cases, the same statement regarding friend declarations still holds true: a friend declaration is only needed for access purposes. As long as the implementation of the operator function relies only on public functions and variables, a friend declaration is not needed.
The operators where the left-hand-side operand is not the class itself. For example cout << somtething can be achieved via defining a std::ostream& operator<<(std::ostream& lhs, Something const & rhs); function, and marking them as friend inside the class.
EDIT: Friending is not needed, ever. But it can make things simpler.
The only reason to use friend function is to access the private(including protected) member variable and functions.
You never need a friend function. If you don't want the operator to
be a member (usually the case for binary operators which do not modify
their operands), there's no requirement for it to be a friend. There
are two reasons one might make it a friend, however:
in order to access private data members, and
in order to define it in the class body (even though it is not a
member), so that ADL will find it
The second reason mainly applies to templates, but it's common to define
operators like + and - in a template base class, in terms of +=
and -=, so this is the most common case.
Operator overloading and friendship are orthogonal concepts. You need to declare a function (any function) friend whenever it needs access to a private member of the type, so if you overload an operator as a function that is not a member and that implementation needs access to the private members, then it should be friend.
Note that in general it is better not to declare friends, as that is the highest coupling relationship in the language, so whenever possible you should implement even free function overloads of operators in terms of the public interface of your type (allowing you to change the implementation of the type without having to rewrite the operators). In some cases the recommendation would be to implement operatorX as a free function in terms of operatorX= implemented as a public member function (more on operator overloading here)
There is an specific corner case, with class templates, where you might want to declare a free function operator as a friend of the template just to be able to define it inside the template class, even if it does not need access to private members:
template <typename T>
class X {
int m_data;
public:
int get_value() const { return m_data; }
friend std::ostream& operator<<( std::ostream& o, X const & x ) {
return o << x.get_value();
}
};
This has the advantage that you define a single non-templated function as a friend in a simple straightforward way. To move the definition outside of the class template, you would have to make it a template and the syntax becomes more cumbersome.
You need to use a friend function when this is not the left-hand-side, or alternatively, where this needs to be implicitly converted.
Edit: And, of course, if you actually need the friend part as well as the free function part.
operators [] -> =
Must be a member functions.
Other binary operators acceptable for overloading can be write in function form or in memeber-function form.
Operators acceptable for overloading is all unary and binary C++ operators except
: . :: sizeof typeid ?

Is it possible to add some functionality to a class without subclassing?

In Ojective-C there is something called Categories which allow the user to add methods from outside the original .h or .m file (objective-c's version of .cpp)
I wonder if there exist such functionally in C++.?
I specially want implement << operator for debugging and maybe others of a class that is in a library I frequently use. (And don't want to use macros since it looks ugly ;) )
Thanks.
You could always overload operators outside of the class.
std::ostream& operator<< (std::ostream& f, const YourClass& cls) {
...
}
You still need to friend this function if it needs to access private members of YourClass.
(But it's not possible to define normal member functions like what Objective-C does.)
Yes, it's possible to add an overload for operator << outside of the class:
ostream& operator <<(ostream& lhs, const SomeClass& rhs) {
/* Output something to lhs using rhs object */
return lhs;
}
The only problem with this is that the function won't have access to SomeClass' private/protected members; to do that you must declare this function a friend inside the class. But if you get all the required information through the public interface, then it's not an issue.
Yes, the Namespace principle is almost similar to this. The idea is to have closely related class operations outside the class in the same namespace as the class. Operator overloading as #KennyTM suggested is a fallout of this principle (the way I look at it)
Also look at the visitor design pattern
Intent
Represent an operation to be
performed on the elements of an object
structure. Visitor lets you define a
new operation without changing the
classes of the elements on which it
operates.

friend in operator == or << when should i use it?

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 !=.

c++ overloaded method in derived class

I have the following question:
Assume base class A with method:
A& operator+(A& a) {...}
I also have a derived class B which overloads (or at least it should so) this method:
A& operator+(B& b) {...}
The problem is that if i want to call something like:
b + a (where b is of type B and a of type A) i get a compile error.
(error C2679: binary '+' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)).
Shouldnt that call the base class method? (it looks like it overrides the method..)
If not, why? Is there a way to fix this (dont tell me to overload the method in B with A&)
Sorry i dont give examples in formated text, but i dont know how to format it.
Thanks in advance!
PS Im using Visual studio 2010 beta.
No, it won't call the base class function. Class B has an operator+, it doesn't take the correct parameter, end of story.
You can define operator+ as a free function, not in any class. Perhaps a friend, if it needs to access private data:
A operator+(const A &lhs, const A &rhs) { ... }
B operator+(const B &lhs, const B &rhs) { ... }
Then b + a will call the first operator, as will a + b. b + b will call the second.
Alternatively, you could "un-hide" the base class implementation, by putting this in class B:
using A::operator+;
it's probably best not to, though. Most operators work better as free functions, because then you get automatic conversions on both operands. C++ never performs conversions on the LHS of a member function call.
Btw, operator+ almost certainly should return by value, not by reference, since an automatic (stack) variable no longer exists once the function returns. So the caller needs to be passed a copy of the result, not a reference to it. For this reason operator+ and inheritance aren't a great mix, although it can probably work as long as the caller knows what they're doing.
The problem is called hiding - a member function in a derived class hides functions with the same name in the base class. In this case you can't access A::operator+(A&) because it's being hidden by B::operator+. The way to fix this is to define B::operator+(A&), and possibly have it call the base class function.
Edit: There's a section in the C++ FAQ Lite that goes into more detail about this problem and offers another possible solution, namely the using keyword.
The problem is that you are defining the member operator, so when called as b + a it results in b.operator+( a ), which doesn't exist.
Accepted practice is to define free operators that themselves would call [virtual] members on the arguments.
Edit:Standard example of what I'm talking about is adapting a class hierarchy for output streaming:
class base
{
public:
virtual ~base();
virtual void print( std::ostream& ) const;
};
std::ostream& operator<<( std::ostream& out, const base& b )
{
b.print( out ); return out;
}
This doesn't really work for math operations since you want to return by [const] value, not reference, i.e. avoid nonsense like a + b = c;.
For example, addition of real and complex numbers is defined, but yields complex number as the result, so you cannot derive complex from real. The other way - maybe. But still you want to define exact operations interface:
const real operator+( const real&, const real& );
const complex operator+( const complex&, const complex& );
Hope this gives you enough to re-think your design :)
Couple of things come to mind. First, you would generally want to make the operator + "virtual". Then, the derived operator + taking a reference to B would be an override due to co-variance, instead of hiding the base class implementation, which is what is happening here.
That said, I suspect (but can't say for certain without compiling a test project) that that would actually solve your problem. That's because the standard answer for binary operators is to use static methods that take two parameters on the class. The C++ STL uses this technique extensively, and I don't know of a reason to attempt to implement binary operators as instance methods, virtual or not. It's just too confusing, with no real up-side.