#include <iostream>
#include <fstream>
using namespace std;
class binaryOperators
{
public:
int i;
binaryOperators (int tempI = 0)
{
i = tempI;
}
binaryOperators operator<< (const binaryOperators &right);
};
binaryOperators operator<< (const binaryOperators &left, const binaryOperators &right)
{
cout << "\nOne";
return left;
}
binaryOperators binaryOperators :: operator<< (const binaryOperators &right)
{
cout << "\nTwo";
return *this;
}
int main ()
{
binaryOperators obj;
// Compiler's behavior: This statement calls the overloaded operator << declared inside the class.
obj << 5 << 3 << 2;
// Compiler's behavior: This statement calls the overloaded operator << declared outside the class.
2 << obj;
return 0;
}
I have written the comments inside the main() function.
What's the reason for this sort of compiler's behavior?
Is this behavior compiler dependent?
GCC on Linux
The behavior you're seeing is caused by const-correctness. The operator<< defined within the class is non-const, so it can only operate on a non-const object or reference, such as obj. The non-member version outside the class has two constant operands.
If you wrote the member version as a non-member, it would look like this:
binaryOperators operator<< (binaryOperators &left, const binaryOperators &right)
{
cout << "\nTwo";
return left;
}
When overload-matching, the compiler chooses the best fit. In the first case, the left operand is non-const, so it chooses the member operator. In the second case, the left operand is an rvalue (temporary binaryOperators), which is referenced as const, so the non-member operator is chosen.
This behaviour makes complete sense:
When a member function exists and matches, then it is a good idea to use it in preference to a free function, otherwise code outside the class could inadvertently break up the class encapsulation (for example, if another member function were to use the operator<<).
Automatic conversion works by creating a list of candidate functions, then attempting to find conversions for any parameters that require it. In order to find the member function, a conversion would have to happen before building the candidate list, so only the free function is found.
Related
When the free operator function and the member operator function are both defined, which one is used for comparison?
#include <iostream>
class A;
class B;
bool operator==(const A &a, const B &b){ return true; };
class A
{
public:
bool operator==( const B &rhs ){ return false; };
};
class B
{
};
int main( int argc, char **argv )
{
A a;
B b;
if( a == b )
{
std::cout << "a==b" << std::endl;
}
};
I ran the code a couple times and it seems that the member operator wins out. Is this always the case?
I ran the code a couple times and it seems that the member operator wins out.
Yes, the member wins in your example. But not for the reason you think.
Member functions have an implicit object parameter (what this points to), and the type of the object parameter is determined by the cv-qualifiers at the end of the member function. In this case, your member operator has no cv-qualifiers, so the type of the implicit object is simply A.
Basically, we have two candidates:
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&, B const&); // your member operator
The member operator is a better match because the first parameter is a better match - we don't have to take a more const-qualified reference to a.
If you had made your operator const (as you generally should), then we'd have these two candidates:
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator
Which are identical, there is no reason to prefer one to the other, and we'd get an ambiguity. There is no rule to prefer a member to a non-member function (or vice versa).
You're declaring the 1st parameter type as const & in the non-member operator. Then given a == b, for the non-member operator to be called a needs to be converted to const. On the other hand the member operator is declared as non-const, then its operand is a non-const A then it's an exact match and wins in overload resolution.
If you change the 1st parameter type of the non-member operator to A& you'll get an ambiguity error. LIVE
Or qualify the member operator as const you'll get the ambiguity error too. LIVE
It is often overloaded as a friend function of the class. Is there any way it can be overloaded as a member function?
Is there any way it can be overloaded as a member function?
Let's say if you have a class Foo and you want to use:
Foo foo;
std::cout << foo;
No, it cannot.
A member function overload works only if the first argument is an object of the class. In the case of stream insertion operators, the first argument is a stream, not an object of the class.
If you want to use:
Foo foo;
foo << std::cout;
Yes, it can be defined as a member function.
A non-member function and a virtual member function can be combined to good effect when used in a situation where derived classes are involved.
struct Shape
{
// Member function that can be overridden by derived classes.
virtual std::ostream& operator<<(std::ostream& os) const = 0;
};
// Non-member function that makes use of member functions.
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape << os;
}
struct Rectangle : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream a Rectangle.
// ...
return os;
}
};
struct Ellipse : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream an Ellipse.
// ...
return os;
}
};
Usage:
Rectangle r;
Ellipse e;
std::cout << r << std::endl;
std::cout << e << std::endl;
If you wanted to badly enough, you could use a member function overload, but it's directly contrary to convention, so doing it would lead to confusion. It would also prevent chaining extraction/insertion operators, and wouldn't work for reading/writing primitive types.
The reason behind this is that invoking an operator overloaded as a member function means that x << y; is interpreted as x.operator<<(y);, so the overloaded operator has to be a member of the left operand, not the right. It's possible to do that (iostreams include such overloads for some types), but it's essentially impossible to extend (all such overloads have to be part of the iostream object when it's the left operand).
If you want to overload it as a member of the object to be read/written, you need to put the object being read/written as the left operand. This means insertion would go from left to right instead of right to left. To have at least some chance of maintaining sanity, you'd almost certainly want to use >> for insertion, and << for extraction:
class my_class {
int x;
public:
bool operator<<(std::istream &is) {
// Note the reversal here. That's because we're defining this
// for a `my_class` on the left, and an iostream on the right,
// but the existing `>>` and `<<` use the reverse of that (iostream
// on the left).
is >> x;
return is.good();
}
bool operator>>(std::ostream &os) {
os << x;
return os.good();
}
};
my_class a;
a >> std::cout;
a << std::cin;
Note: I'm providing this answer only to point out that it's technically possible to do this, and show how. If you were starting over with a clean slate and you were really set on using member functions, I can see where you might conceivably choose this method--but even then, it's open to a lot of question.
In particular (as noted above) this would not support chaining. Since the insertion and extraction are done as member functions of the left operand, it also means it would only work for user-defined types, not any primitive types (int, short, long, float, double, bool, etc.)
Bottom line: if you want to badly enough, you can get it to work to a limited degree under limited circumstances--but neither well (no chaining) nor universally (no primitive types).
Is there any way it can be overloaded as a member function?
No. The signature of the function prevents this option.
// Binary operator where the stream object is left of '<<' and the object
// instance is right of '<<'
std::ostream& operator<<(std::ostream& lhs, const Foo& rhs)
For illustration here's a binary operator+ as a free function:
class Foo
{
};
Foo operator+(const Foo& lhs, const Foo& rhs)
{
// an appropriate implementation
}
int main()
{
Foo f1;
Foo f2;
// Uses the free function
Foo result = f1 + f2;
return 0;
}
However implemented as a member function it looks like this:
class Foo
{
public:
Foo operator+(const Foo& other) const
{
// an appropriate implementation
}
};
int main()
{
Foo f1;
Foo f2;
// The calling sequence is the same as before however 'f1' is logically
// the same as 'lhs' in the free function implementation example (i.e.,
// the first type in the binary operator must be the class type when
// implemented as a member function)
Foo result = f1 + f2;
return 0;
}
Given the operator+ member function example it is easier to see why the std::ostream& operator<<(std::ostream& lhs, const Foo& rhs) free function cannot be converted to an equivalent member function. Because 'lhs' would need to be the same type as std::ostream but this is only possible when implementing that class whereas in this example the Foo class is being implemented.
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.
I have this class definition:
class foo{
public:
foo();
foo(const int& var);
foo(const foo& var);
~foo();
const foo operator +(const foo& secondOp) const;
private:
int a;
//plus other values, pointers, e.t.c.
};
Also I have made this implementation for '+' operator overloading:
const foo foo::operator +(const foo& secondOp) const{
//I want here to check if i have one operand or two...
if ((FIRST_OPERAND.a!=0) && (secondOp.a==0)){
cout << "ERROR, second operand is zero";
return FIRST_OPERAND;
}
else if ((FIRST_OPERAND.a==0) && (secondOp.a!=0)){
cout << "ERROR, first operand is zero";
return secondOp;
}
}
When i write in main():
foo a(2);
foo b;
foo c;
//I want here to print the ERROR and
//return only the values of a
c = a + b;
Ηow can i return the value of the first operand if the second operand is zero and vice versa?
You're almost there. Since it's a member function, the first operand is *this, so replace FIRST_OPERAND.a with this->a or just a.
However, it might be better to make it a non-member function to allow conversions on both operands (i.e. to be able to write a + 2 or 2 + a). It will need to be a friend in order to access the private member(s).
friend foo operator +(const foo& firstOp, const foo& secondOp);
Also, it's best not to return a const value as that prevents moving from the return value.
It is the compiler that checks the syntaxical correctness of the program. It is unable to distinguish whether you indeed wanted to write
c = a;
that is to do the assignment or you wanted to write
c = a + b;
The both statements are correct.
It is a so-called logical error. The compiler is unable to see what we thoght.
For your line c = a; The assignment operator is implemented by the compiler (just shallow copying the object memory).
That is the reason your code compiles "without the second operand".
If you wish to disallow using the assignment operator - hide it. E.g. by implementing with the private access modifier.
You have to define this function as a friend function
friend Int operator + (int first, Int &second);
this function can perform obj + 2 or 2 + obj.
Int operator + (int first, Int& second){
second.a += first;
return second;
}
While answering this question I came across an interesting difference in the overload resolution of rvalue to reference between member and non-member operators.
Given two non-member operators, one passing the left parameter as const and one as non-const, both GCC 4.4.3 and MSVC2010 choose the const version when called with an rvalue.
However, given two member operators, one const and one non-const, both compilers choose the non-const version.
I assume that both compilers are complying with the standard on this, so I am curious as to why there is this discrepancy between const overload resolution between members and non-members. Please enlighten me :)
Here's some code to illustrate the difference:
#include <iostream>
class C {
public:
C(int i) { }
/*
C operator<<(C const &rhs) {
std::cout << "member non-const" << std::endl;
return *this;
}
C operator<<(C const &rhs) const {
std::cout << "member const" << std::endl;
return *this;
}
//*/
};
C operator<<(C &lhs, C const &rhs) {
std::cout << "non-member non-const" << std::endl;
return lhs;
}
C operator<<(C const &lhs, C const &rhs) {
std::cout << "non-member const" << std::endl;
return lhs;
}
int main() {
// Will print:
// "non-member const" when member operators are commented out
// "member non-const" when members are uncommented
C(5) << 6;
}
Rvalues cannot bind to references-to-nonconst, so only the reference-to-const overload of the free function is viable: operator<<(C(5), 6);.
This does not apply to the member-operator, which is simply C(5).operator<<(6), and the C-object isn't a function argument. You would have to say static_cast<const C &>(C(5)) << 6 to get the const version there, since it is the constness of this that distinguishes the two member operator overloads.
In the presence of both member and free-function operators, the member function is preferred, so putting all this together explains the observed behaviour.