Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I tried to analyse why some of the operators ((), [], ->, =) should be overloaded as member functions only. I failed and I tried to search on internet but of no use. Can any one please help me to understand this restriction?
I think this is most likely why that portion of the standard was written that way.
but if it is not forbidden, the friend version would never be called, in my testing code ,when
Complex operator+(const Complex &other);
is defined as private, the compiler would
give error message
‘Complex Complex::operator+(const Complex&)’ is private
Complex Complex::operator+(const Complex &other)
instead of using the friend version
refer to Why cannot a non-member function be used for overloading the assignment operator?
Because the default operator= provided by the compiler (the memberwise copy one) would always take precedence. I.e. your friend operator= would never be called.
(If the assignment was performed inside a class method, because of the lookup rules, the member function (in this case generated by the compiler) would take precedence)
I try to using operator + for test. it prove the precedence
it outputs:
member function called
7+11i
testing code:
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(int real, int imag);
Complex(void);
~Complex(void);
Complex &Add(const Complex &other);
void Display() const;
Complex operator+(const Complex &other);
friend Complex operator+(const Complex &c1, const Complex &c2);
private:
int real_;
int imag_;
};
Complex::Complex(int real, int imag): imag_(imag), real_(real)
{
}
Complex::Complex(void)
{
}
Complex::~Complex(void)
{
}
Complex &Complex::Add(const Complex &other)
{
real_ += other.real_;
imag_ += other.imag_;
return *this;
}
void Complex::Display() const
{
cout << real_ << "+" << imag_ << "i" << endl;
}
Complex Complex::operator+(const Complex &other)
{
int r = real_ + other.real_;
int i = imag_ + other.imag_;
std::cout << "member function called"<< std::endl;
return Complex(r, i);
}
Complex operator+(const Complex &c1, const Complex &c2)
{
int r = c1.real_ + c2.real_;
int i = c1.imag_ + c2.imag_;
std::cout << "friend function called"<<std::endl;
return Complex(r, i);
}
int main(void)
{
Complex c1(3, 5);
Complex c2(4, 6);
Complex c3 = c1 + c2;
c3.Display();
return 0;
}
Certain forms of operators require access to the "this" pointer of an instance of a class in order to operate directly on that instance as they only take a single argument to the same type.
class A{
public:
int x;
// only takes a reference to another 'A' type, so we need the 'this' pointer
A& operator=(const A& other){
this->x = other.x;
return *this;
}
};
Although maybe not very satisfying, here's what the standard has to say about it:
(emphasis is mine)
§3.5.3 Assignment
An assignment operator shall be implemented by a non-static member function with exactly one parameter.
§3.5.4 Function call
operator() shall be a non-static member function with an arbitrary number of parameters.
§3.5.5 Subscripting
operator[] shall be a non-static member function with exactly one parameter.
§3.5.6 Class member acess
operator-> shall be a non-static member function taking no parameters.
I can't speak to the reasoning behind these requirements, so I will leave that aspect to those that are more familiar with how compilers are designed.
Related
In C++, if you've got a class Foo, and you want users of Foo to be able to write:
Foo x;
x += 3;
, you can simply make a member function of Foo, Foo& operator+=(int rhs). If you want to be able to write:
Foo x;
int y = 3;
y += x;
, you cannot accomplish this by writing a member function of Foo, instead one has to write an external function, which usually must be declared as a friend of Foo.
How hard would it be for a future version of C++ to say that this can be written with a Foo member function int& operator+=(int &lhs, Reversed), where Reversed was some empty class whose sole purpose was to distinguish the two versions of the operator?
If this were done, it could probably eliminate the vast majority of the uses of the friend keyword in new code.
You can in fact define such an operator, because you are free to overload += for built-in types:
int& operator+=(int &lhs, Foo &rhs) {
lhs += rhs.somefield;
return lhs;
}
On the other hand, instead of writing overloaded functions for all possible operators, you can also provide a function that will allow implicit casts of class Foo to int:
class Foo {
... somefield;
operator int() {
return (int)somefield;
}
};
Sometimes a non-member function may need access to the private members it's taking in as a agrument.
A friend function is a non-member function that gives private access to the classes it's friends with.
Class X{
int number;
public:
X& operator+=(const X& rhs);//a += b is a.operator(b)
friend int& operator+=(int& addthis, const X& rhs);//add this += b is I don't know what lol
}
X& operator+=(const X& rhs){
this->number = this->number + rhs.number;
}
int& operator+=(int& addthis, const X& rhs){
addthis = addthis + rhs.number;
return *this;
}
What I read is that if I wanted to do += to an object, object += int, just overload the += operator, but what if the int came before the object. Say int += object? Than I would have to write it as a friend function, and that's where I get a little lost. Why can't I just write int& operator+=(int& addthis, const X& hrs); as a member function? I assume a friend function can work with other classes since it's a non-member function, so it's not assigned to any specific class?
I'm sorry I just don't understand why I would use friend function over making it a member function. Really would appreciate any feedback, thank you.
You can enable the operator+= for int and other integral types via a user-defined conversion in your class X:
struct X{
int number;
operator int() const
{
return number;
}
//...
}
Of course, this doesn't give you exactly the same behaviour as your friend-approach, as other functions could also use the conversion. Nevertheless, I guess this is what you are looking for, as otherwise you would need to define as well operator-=, operator*= and so on.
As far as I understand, you can't have operator*, operator+ or operator+= or any of operator# where # is some math operator that returns something other than an instance of your class right in the definition of your class.
In real world, it would be quite odd to add an integer to an integer and get an apple as a result. The same should apply to classes in C++. A member function is, well, a property of the class, a function that represents whatever can be done to the object of this class. Operators are special. They represent operations that sort of can't be made easier (what will you use to code an addition operator using the + sign instead of operator overloading?). They represent the very basic operations and thus should return an instance of the class they're members of.
Consider you implemented operator overloading as member function and performed something like x += y where both x and y are objects of the class which has the operator += overloaded.
Compiler parses x += y as x.operator+=(y) which is fine as both operands x and y are of the same class which has the operator += overloaded.
Now consider an expression like 2 += y (this may be insane, but I am trying explain why operator overloading with friend functions may be at time beneficial over operator overloading with member functions)
Since, the expression 2 += y will be parsed by compiler as 2.operator+=(y), an error is raised. Maybe 2 may get converted to an object of the class using constructor for conversion; (Single argument constructors can be used for conversion) but that is not the point here.
Using friend function to overload the operator calls the above expression 2 += y as operator+=(2, y) which works fine.
The reason why the operator int += X has to be a free function is that the compiler only searches for applicable member operators in the lhs type, and not in the rhs type. Since int is not a type that can be extended, you can't define this operator as a member function.
You were almost there, just a few errors:
class X;
int operator+=(int addthis, const X& rhs);
class X{
int number;
public:
X& operator+=(const X& rhs);//a += b is a.operator(b)
friend int operator+=(int addthis, const X& rhs);//add this += b is I don't know what lol
};
X& X::operator+=(const X& rhs){
this->number = this->number + rhs.number;
return *this;
}
int operator+=(int addthis, const X& rhs){
addthis = addthis + rhs.number;
return addthis;
}
some forward declarations added
int passed by value instead of by reference
missing semicolon after class declaration
class instead of Class
return corrected
Note that X += int is a member function, while int += X is a free function, declared a friend of the class X.
Using a free function for int += X is the only solution that allows to use the operator as usual, like:
X x;
int i = 2;
i += x;
The friend modifier is just meant to expose private data. Normally, you wouldn't define a friend function as a non-member if it only depends on the private data of a class it can be defined as a member function for.
A better example would be ostream::operator<< or istream::operator>>.
Learning Expression templates.
In Wandevoode and Jossutis's book Templates, the complete guide, section 18.2.3 The Operators, they define an operator+ with two arguments but not as a friend method.
template <typename T, typename R1, typename R2>
Array<T,A_Add<T,R1,R2> >
operator+ (Array<T,R1> const& a, Array<T,R2> const& b) {
return Array<T,A_Add<T,R1,R2> >
(A_Add<T,R1,R2>(a.rep(),b.rep()));
}
I am a beginner and hence insecure about what I know about C++.
Shouldn't this operator+ be a friend?
I tried
class A{
public:
explicit A(int x) : a(x){};
A& operator+(const A& x, const A& y){
A temp{x.a + y.a};
return temp;
};
private:
int a;
};
I am getting a binary 'operator+' has too many parameters.
Your "binary" operator + member function gives you the "too many parameters" error because it has three parameters: the x and y you specified, plus the implicit this parameter. This means it actually takes three arguments, which of course is impossible.
You can make a member function taking one explicit parameter and the implicit this, but in the opinion of many people, these binary operators such as add and subtract are better implemented outside the class, in the same namespace as the class, as free functions taking two explicit parameters. This works especially well if the data needed to fulfill the operation can be publicly accessed (otherwise you must use friend, which is OK if truly necessary).
To summarize for the next reader.
There seem to be three forms of overloading binary arithmetic operators.
First: A member method taking one parameter by const reference. The const tothe return value is used (according to this reference) to avoid (x+y)=z.
class A{
const A operator+(const A& other){
// ...
};
};
Second: A friend method, and therefore included in the definition of the class, taking two parameters.
class A{
friend A& operator+(const A& operand1, const A& operand2){
// ...
};
};
Third: A non-member method taking two parameters.
class A{
// ...
};
A operator+(const A& operand1, const A& operand2){
// ...
};
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When should you use 'friend' in C++?
There is a detailed explanation here, but I would like to know what is the practical use of Friend function.
How I can decide when I should go with a friend function rather than a member function?
In most cases, friend declarations are a code-smell since it breaks encapsulation.
Developers often use friend for a quick-fix to a problem. However a good starting design or some refactoring (more often more than less) exclude the necessity for it.
EDIT:
Even in #Darhuuk's example, a friend declaration is not needed. You can have getters for the specific fields you want to print.
You would use a friend when the function needs to be a non-member, but also needs access to class members.
Common examples where you need a non-member function are:
An API that requires non-member functions; for example, boost::intrusive_ptr requires that you implement intrusive_add_ref() and intrusive_release() as non-member functions.
Overloading a binary operator where your type need to be the right-hand operand; for example operator<<(ostream&, my_type const &).
Overloading a binary operator where you want the left-hand side to be convertible to your type; for example, if your class is constructible from int, then 5 + my_type will work if you define a non-member operator+(my_type const&, my_type const&);, but not if you define a member my_type::operator+(my_type const &) const;.
Whether any of these needs to be friends depends on whether they can do their job using the class's public interface; for example, you could add a public print(ostream&) member that operator<< could use, and a public operator+= member that operator+ could use.
As an example of implementing operator+ in terms of operator+=:
my_type & my_type::operator+=(my_type const & rhs)
{
// do addition here
return *this;
}
// The first operand is passed by value, giving a modifiable copy
my_type operator+(my_type lhs, my_type const & rhs)
{
return lhs += rhs;
}
The simplest use case would probably be when overloading the stream output operator for a custom class.
For example, take a look at the following code (shamelessly copied from here). In this case the use of friend allows the non-class method to access the private fields of class, thus preventing the need to code several get methods (which otherwise you might not even want to create).
#include <iostream>
#include <cstring>
using namespace std;
class MyClass {
// now private
char name[80];
int areacode;
int prefix;
int num;
public:
MyClass(char *n, int a, int p, int nm)
{
strcpy(name, n);
areacode = a;
prefix = p;
num = nm;
}
friend ostream &operator<<(ostream &stream, MyClass o);
};
ostream &operator<<(ostream &stream, MyClass o)
{
stream << o.name << " ";
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n";
return stream;
}
int main() {
MyClass a("T", 1, 5, 1);
MyClass b("A", 3, 5, 5);
MyClass c("T", 2, 5, 9);
cout << a << b << c;
return 0;
}
The assignment operator can be declared as
T& operator= (const t&);
in a class, but the arithmetic operators cannot be defined that way. It has to be friend function. I don't understand why? Can you please explain ?
It is not mandatory that arithmetic operators should be friend
Well you can define like this:
MyClass MyClass::operator + (const MyClass& t) const
{
MyClass ret(*this);
ret += t;
return ret;
}
The a + b is really a syntax sugar, the compiler will expand it to a.operator+(b). The previous sample will work if all your objects are MyClass instances, but will not work if you have to operate with others types, ie 1 + a, will not work, this can be solved by using friends.
MyClass operator + (int i, const MyClass& t)
{
MyClass ret(i);
ret += t;
return ret;
}
This has to be done when the left hand side of the + operator is not a class, or it is a class but you can't add operator + to its definition.
I think that C++ FAQ Lite will give you a definitive answer.
They ideally should be globals and not necessarily friends, so that you can write:
yourtype v = 1;
yourtype w = 1 + v;
Since, 1 is not an object of yourtype, if the operator+ were a member it would throw a fit. However, making it global makes it convert the 1 to yourtype and then perform the operation. Making it a friend helps to extract and manipulate the members of yourtype as required -- though not required. As an example: You can implement the member function operator+= and use it in the implementation of the operator+.
The problem is that if you do something like this:
class A
{
A& operator+(int n);
// ...
}
int main()
{
A my_var;
int integer = 1;
A + integer; // compiles
integer + A // error: no function operator+(int, A) defined
}
it will not compile.
A solution is to define operator+(int, A) and operator+(A, int) as friends of A.
As a side note, the Boost Operators library makes this process very easy.