Operator overloading > Friend Function >

Suppose that the operator << is to be overloaded for a user-defined class mystery. Why must << be overloaded as a friend function?
Last edited on
It is not necessary. It is usually done because this function often accesses the private and protected members of the object it displays.
It's necessary. A friend function is the only way of implementing an
overloaded operator<< or operator>> function.
Last edited on
It is not necessary that operator << shall be defined as a friend function. It can be a member of a class or usual function. For example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

int main()
{
	class Int
	{
	public:
		Int( int x = 0 ) : i( x ) {}
		const Int operator <<( size_t n ) const
		{
			return ( Int( i << n ) );
		}
		std::ostream & out( std::ostream &os ) const
		{
			return ( os << i );
		}
	private:
		int i;
	} i1( 1 );

	std::cout << "i1 << 1 = "; i1.operator <<( 1 ).out( std::cout ) << std::endl;

	return 0;
}
Last edited on
I will even rewrite my example that it would be more clear.:)

Here there are two overloaded operator <<. One of them is a member of the class and other is a usual (non-friend) function.:)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

class Int
{
public:
	Int( int x = 0 ) : i( x ) {}
	const Int operator <<( size_t n ) const
	{
		return ( Int( i << n ) );
	}
	std::ostream & out( std::ostream &os ) const
	{
		return ( os << i );
	}
private:
	int i;
};

std::ostream & operator <<( std::ostream &os, const Int &x )
{
	return ( x.out( os ) );
}
   
int main()
{
	Int i1( 1 );
	std::cout << "i1 << 1 = " << ( i1 << 1 ) << std::endl;

	return 0;
} 


Moreover such an operator can be defined as a static member function of a class.
Last edited on
I'm really thankful to you. You've given me a new concept. I'll clarify everything about this new concept from my teacher.

Actually my concept is:
In order for a function (operator or otherwise) to be a member function, it must have a
first parameter of the class type. The << and >> operators require that the left (first)
parameter be the stream (file) and the right (second) parameter be the class object.
Therefore it is not possible for the operator<< or operator>> functions to have a first
parameter of the class type. A friend function is the only way of implementing an
overloaded operator<< or operator>> function.


Am I wrong with this concept?
Last edited on
You are not wrong on this concept. Vlad is showing you that it is possible to find an alternate solution, however it requires an extra public function. I believe the answer that your instructor is fishing for is this:

If you define an overloaded operator inside of a class, this needs to be on the left. You cannot define an overloaded operator inside the class that puts this on the right. (with the exception of operator++)

The common alternative is to define the overloaded operator outside of the class. This allows us to put the class on the right, however to access private members, the function must be given friend privileges.

Vlad proposed a solution where he provided an accessor function that could only be called with what would normally be the left-hand-side of the operator. It's a brilliant alternative, but I don't think it's easier or clearer than providing friend privileges. Vlad is the kind of guy that takes questions very literally and I'm pretty sure that he's memorized the entire C++ standard.
Last edited on
Am I wrong with this concept?


The only part of it that is wrong is:
A friend function is the only way of implementing an overloaded operator<< or operator>> function.


It happens frequently that data that would be printed via operator<< is also available via the public interface of the class. For instance the Int class as defined above is practically useless with no way to access it's value.

In the code below you'll notice that operator<< is neither a friend nor a member of Int, but still manages to work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

class Int
{
public:
    Int( int x = 0 ) : i( x ) {}

    operator int() const { return i ; }

private:
    int i;
} ;

std::ostream& operator<<(std::ostream& os, const Int & theInt)
{
    return os << static_cast<int>(theInt) ;
}

int main()
{
    Int anInt = 9 ;
    std::cout << anInt << '\n' ;
}
Last edited on
How operator << is able to access a private member?
I changed the names in the code, so it is obvious that operator<< is not accessing a private member.
So cire, what is happening in your code is that you're tye casting an object directly into an int and that's giving the value of private member through the operator function ()?

You guys have used a brilliant way. I would be very thankful to you guys if you can recommend me a book for learning and mastering C++. Please...
Request to cire, vlad and Stewbond.
Last edited on
So cire, what is happening in your code is that you're tye casting an object directly into an int and that's giving the value of private member?


Sort of. Overloaded operators are really just syntactic sugar for invoking functions. The code could also have been written:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

class Int
{
public:
    Int( int x = 0 ) : i( x ) {}

    operator int() const { return i ; }

    int get() const { return i ; }

private:
    int i;
} ;

std::ostream& operator<<(std::ostream& os, const Int & theInt)
{
    return os << theInt.operator int() ;
    // or, same principle:
    // return os << theInt.get() ;
}

int main()
{
    Int i = 9 ;
    std::cout << i << '\n' ;
}


Coincidentally, the following would also work as providing operator int for an Int means it will match an existing overload of operator<<.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

class Int
{
public:
    Int( int x = 0 ) : i( x ) {}

    operator int() const { return i ; }

private:
    int i;
} ;

int main()
{
    Int i = 9 ;
    std::cout << i << '\n' ;
}


Topic archived. No new replies allowed.