You are here:

C++/C++ Operator Overloading

Advertisement


Question
Good morning,

I am playing with C++ and am wanting to overload the insertion operator << for a defined class Foo. But I don't want the Foo class to be a friend of any other class. It makes sense to define it as a friend of ostream but how do I code it without doing this? Since the calling object is not of type Foo it can't be a member function, so what do I do?

Thanks in advance for your help,
Jerome

Answer
First I must apologise for the delay in replying to your question. I went out shortly before you posted your question (around 18:00 in _my_ time zone in the UK) and was away somewhat longer than expected. I have only just now picked up my email and received your question.

Anyhow, I think your problem is that you have got the friendship requirements backwards. You need to make your operator<< function a friend function of the Foo class so that the operator<< can access private and protected parts of Foo objects to insert them into the required stream. A similar argument goes for the companion operator to the insertion operator, the extraction operator operator>>.

You cannot (well, should not, really, really should not) add friends to existing classes unless you are responsible for their maintenance - which is not the case with std::ostream or std::istream (in fact these are typedef aliases anyway!). The same goes for adding members including operator member functions to such classes.

This is why operator<< and operator>> are always implemented as non-member functions:

   class Foo
   {
     // The non-member operator<< is a friend of Foo so it can
     // access all parts of Foo objects
      friend std::ostream & operator<<( std::ostream &, Foo const &);

   // ...

   };

   // Declaration of non-member operator<< for Foo objects.
   // The operator<< function is defined elsewhere.
   std::ostream & operator<<( std::ostream & out, Foo const & foo );

You can get around the need to make operator<< a friend at all by providing some public member function of Foo that effectively does the same thing and then defining operator<< in terms of calling this function on the Foo object it is passed:

   class Foo
   {
   public:
       // The Print member function does the work of writing a
       // Foo to a std::osteam object and is defined elsewhere.
       // Note that Print is a const member function as outputting
       // data should not require modification to the Foo instance.
       std::ostream & Print( std::ostream & out ) const;
   };

   // The non-member operator<< function calls Print on its Foo
   // object parameter passing it the std::osteam parameter and
   // returning what the Foo::Print member function returns.
   inline
   std::ostream & operator<<( std::ostream & out, Foo const & foo )
   {
       return foo.Print( out );
   }

This also allows us to make the Print member function virtual if necessary so if Foo were a base class of a family of classes then we only require a non-member operator<< function for the Foo base class. Any object of a class that derives from Foo can be passed as a Foo reference to this function and the Print virtual member function will be called polymorphically. See Scott Meyers book "More Effective C++", item 25 "Virtualizing constructors and non-member functions." for another example.

Other times friend relationships are not required are when all data that needs to be accessed are public, for example classes formed from the std::complex<typename T> class template such as std::complex<double>, or when the data can be accessed via the public interface of the class anyway as in the case of std::string. Note that in general data members should be private so cases such as std::complex<typename T> should be rare. Even cases such as the std::string case should be quite rare as usually not all the information needed to output an object's state is accessible via the public interface. Basic types such as complex number and string classes tend to be exceptions to such rules because they are simple and general.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.