You are here:

C++/c++ operator overloading

Advertisement


Question
hi..
i want to know how the operator over loading functions are invoked..for example

how s1+s1(both are objects) will invoke
class_name operator(class_name object_1)
if my question is not clear please give me an example and explanation for operater verloading....
with thanks.. sathish

Answer
I do not know if you really intended to say:

   s1+s1

in your question, but maybe instead meant:

   s1+s2

as you go onto say both are objects implying two objects and not just one are involved. I shall assume the latter.

The compiler sees that s1 and s2 are objects of some type(s) for which it has no built-in addition operation, so it goes looking in what it knows about these types and user defined overloaded operator functions to see if it can find an overloaded operator function it can call to perform the addition operation for the types of the objects s1 and s2.

One place it will look is the class definition for the type of s1 to see if there is an operator+ member function defined that takes an object of s2's type as a parameter:

   class S1Type
   {
   public:

   // ...

       S1Type operator+( S2Type const & rhs ) const
       {

       // ...

       }

   // ...

   };

Here I have assumed the types of s1 and s2 are different. Notice that I call the S2Type parameter passed to the S1Type operator+ function rhs - short hand for right hand side. This is because this parameter appears on the right hand side of the binary (meaning it takes 2 operands) + operator. This means that s1+s2 would work but s2+s1 would not unless S2Type defined an operator+ function that took an S1Type as a parameter. As I assume s2 is a class type that may be quite large I pass it by constant reference rather than by value. Constant reference is used as the operation should not need to modify the operands. This is also why I declare the operator+ member function const - the s1 (this) object should not be modified either.

So effectively when the compiler sees:

   s1 + s2

It looks for a suitable operator+ function. If it finds one and it is a member function of s1's type (S1Type in my examples) then it is as if it replaces the (sub-) expression:

   s1 + s2

with a call to S1Type::operator+(S2Type const &):

   s1.operator+(s2)

The result in this case is an object of s1's type, which has the result of adding s2 to it. However it could be an object of s2's type (S2Type in my examples) or some other type. Note that this follows the usual meaning of a binary + operation: neither of the operands is modified, rather they produce a third object as the result.

The other type of overloaded operator function the compiler looks for is a non-member overloaded operator+ function:

   class S1Type
   {
   public:

   // ...

   };

   class S2Type
   {
   public:

   // ...

   };

   S1Type operator+( S1Type const & lhs, S2Type const & rhs )
   {

   // ...

   }

Here the function takes two parameters - the left hand side value and the right hand side value. If this were the operator+ function chosen for our (sub-) expression then it would be as if the compiler replaced:

   s1 + s2

with a call to the non-member operator+ function:

   operator+(s1, s2)

Non-member overloaded operator functions have to be used in some cases as the left hand side is not of an appropriate type. An example are the stream insertion and extraction operators (operator<< and operator>>). In these cases to be a member function would mean the stream classes would need to be updated with new operator functions for every type that wished to support stream insertion and extraction syntax:

   std::cout << s1;

   std::cin >> s2;

   etc.

as it is the stream objects that are on the left hand side. This is somewhat impractical even if they were not standard C++library types. As they are standard library types they definitely should not be modified by users of the library (i.e. every day C++ developers like you and me) and indeed cannot be according to the standard. So instead we write operator<< and operator>> functions for our own types as non-member functions.

Of course if in its search for an appropriate operator function to handle the addition the compiler finds no suitable functions or more than one of equal viability then the program is in error.

Finally I should point out that the compiler has to search in various scopes for non-member overloaded operator functions and for classes with member functions. In fact this is a general rule for any non-member functions. It is only a problem for member functions of overloaded operators as direct member function calls require an object of the class type or the (qualified) class name for static member functions, in which case the compiler has effectively already been told where to look for the class definition!

So not only does the compiler search the current scopes (namespaces) where the call occurs for matching function overloads (operator functions or otherwise), as is usual and expected, it _also_ looks in the namespaces where the types of any arguments are defined.

This is because it is likely if you define a class C in some namespace N then you would declare any non member functions related to class C - such as non member overloaded operator functions for class C objects - in the same namespace.

Hence when using class N::C objects, say from some other namespace X and performing operations on them the compiler would fail to locate the non-member functions relating to class C if it only looked in namespace X and outwards (e.g. the global namespace).

Likewise if when looking for candidate overloaded operator functions it only looked in the current scope and outwards (e.g. namespace X and the global namespace) it could miss class member overloaded operator functions of the types of the parameters, as it would miss the definition for the types (e.g. the definitions of class C in namespace N).

The compiler therefore has to look also in the namespaces of the parameters (or operands for overloaded operators) (e.g. namespace N and namespace std). This is shown below:

   namespace N
   {
       class C
       {

       // ...

       public:
         C operator+( C const & rhs ) const

       // ...

       };

   //---------------------------------------------------------------------------
   // Output stream insertion operator for class C.
   //
   // Allows us to write:
   //
   // C c;
   // std::cout << c;
   //
       std::ostream & operator<<( std::ostream & out, C const & rhs )
       {

       // ...

         return out;
       }

   }


   namespace X
   {
   //---------------------------------------------------------------------------
   // Function using class C, adding two N:C objects
   // and displaying results on std::cout:
   //
      void function_using_class_C
       {
         N::C c1(2,3);   // Need to qualify C with its containing namespace N
         N::C c2(4,5);   
       
       // If the compiler did not also look in the namespaces of the types
       // of the parameter operands std::cout (in std) and c1 and c2 (in N)
       // then std::ostream & N::operator<<( std::ostream &, N::C const & )
       // and N::C N::C::operator+( N::C const & ) could not be found and the
       // following line would raise one or more compiler errors.
         std::cout << c1 << " + " << c2 " = " << c1 + c2 << '\n';
       }

   }

I hope this answers your query. If it does not, or you are unclear on anything in my answer then please do post a follow-up or new question.  

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.