Declaring Overloaded Member Functions in a Class

The idea of overloading is to use the same name for more than one function in a class.

This can be useful when you have separate names for functions that do essentially the same thing, but differ only in the number or types of arguments required. For instance, anExternalInterface has member functions DisplayText(), DisplayRequest(), and DisplayNumber(). Wouldn't it be nice to be able to just call a function named Display() and have the compiler figure out which implementation to call based on the arguments provided?

C++ makes this fairly simple.

For instance, to the compiler, the following declarations represent separate and distinguishable member functions of anExternalInterface, despite having the same name:

void Display(const char *theText) const;
void Display(const aRequest &theRequest) const;
void Display(const float theNumber) const;

Once you have defined these, you can call them:

myExternalInterface.Display("Some text");
myExternalInterface.Display(theRequest);
myExternalInterface.Display(1.5);

These statements compile and run without compiler or runtime errors. Control flows to the correct implementations without any special work on your part.

Overloading is as simple as that. (At least, the basics are.)

How the Compiler Finds the Right Function

The compiler connects a member function call with its implementation by taking the class of the object, the name of the function called, and the sequence of the types of the actual arguments used in the function call (this is called the function call's signature). This call signature is checked against the implementation signature (the class, the name of the function, and the sequence of the types of the formal arguments for each implementation). The implementation whose signature best matches the signature of the call is the one that will be used.


The compiler's idea of the best match and your idea of the best match may not be the same if you have several functions that offer very similar argument types in the same order.

You have a few alternatives that can help keep your overloaded functions distinct. These will ensure that you get the results you expect:

  • Try to make sure that your overloaded function argument types are as distinct as possible. For instance

    void SomeFunction(const int theFirst, const int theSecond, const long theThird);
    

    and

    void SomeFunction(const int theFirst, const long theSecond, const int theThird);
    

    are very similar and can be difficult to resolve for a call such as

    SomeFunction(3,4,5);
    

    In this situation, you might reconsider the overload and simply provide a “lowest common denominator” that can deal with int or long for any argument:

    void SomeFunction(const long theFirst, const long theSecond, const long theThird);
    
  • You can change the order of arguments to make the overload distinct. For instance

    void SomeFunction(const const int theFirst, const int theSecond, char theThird);
    void SomeFunction(const int theFirst, long theSecond, char theThird);
    

    could be replaced by

    void SomeFunction(const int theFirst, const int theSecond, char theThird);
    void SomeFunction(char theThird, long theSecond, const int theFirst);
    

    This would force a caller of the second function to make the call distinct by placing the character as the first argument rather than the last.

  • Keep the number of arguments low. One of the purposes of creating objects rather than procedural programs is to leverage the capability of the object to maintain internal state. There is nothing wrong with a sequence of calls such as

    SomeObject.SetFirst(3);
    SomeObject.SetSecond(4);
    SomeObject.SetThird(5);
    SomeObject.DoSomething();
    

    or

    SomeObject.SetFirst(3.2);
    SomeObject.SetSecond("4.2");
    SomeObject.SetThird(5);
    SomeObject.DoSomething();
    

    These calls leverage overloading as well as the capability of the object to maintain internal state. When DoSomething() is called, it works with whatever values have been set by prior function calls on the object.

Keep in mind that C++ does not use the function's return value type as part of the signature. Because of this, the following two declarations have the same signature and will cause a compiler error:

void Display(const char *theText) const;

int Display(const char *theText) const;

Overload Resolution

The process of matching a function call signature with a function implementation/ definition. This process is also called resolving. In C++ this occurs at compile time; the compiler generates code to make the appropriate call or produces an error message if the call cannot be resolved.


Default arguments can cause problems for overloading. For instance, imagine two functions for anExternalInterface with these signatures:

void Display(const char *theText) const;
void Display
(
   const char *theText,
   const int thePadWidth = 12
) const;

The compiler will find it difficult to tell whether

ExternalInterface.Display("Stuff");

means to call

void Display(const char *theText) const;

or

void Display
(
   const char *theText,
   const int thePadWidth = 12
) const;

because the presence of a default value for the second argument leaves open the possibility that you intended to call the second function, but used only one argument. So the signature of the call matches both implementations.

The compiler will let you compile these functions into your class. However, when a program actually calls the function and only provides a literal string as an actual parameter, you get a compiler message that looks like this:

[C++ Error] Ambiguity between
'SAMSCalculator::anExternalInterface::Display
   (const char *) const' and
'SAMSCalculator::anExternalInterface::Display
   (const char *,const int) const'

Here, the compiler is telling you that it can't see the difference between the two functions (the overload is ambiguous). There is nothing you can do to change this except eliminate the default argument.

Instead of a default argument, provide these two functions:

void Display(const char *theText) const;

void Display
(
   const char *theText,
   const int thePadWidth
) const;

Have the first function assume a “PadWidth” of 12.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.253.4