Contents  1-5  6-11  12-16  17-21  22-27   28-33  34 - 38  39-46  Projects   MFC

   Contact
   Search
   C
   C++
   Visual Basic
   Java
   JavaScript
   DHTML
   Style Sheets
   About
   Active X
   TDC Binding
   PHP
   Perl and CGI
   Flash
   XML
   SQL
   Messages
   Chat
   MCSE
   Linux
   Cabling   
   ActionScript
   Downloads
   E-Cards   
 
    
    

Overriding functions - Overriding functions involves changing the implementation of a base class function in a
derived class.  When you make an object of the derived class, the correct function is called, specific to the type
of the child object rather than the parent object it inherits from.  It is when a derived class creates a function
with the same return type and signature as a member in the base class, but with a new implementation.  It is "overriding" that method. When you override a function, it must agree in return type and signature with the function in the base class.  Recall the definition of a function's signature:

"If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside." - Robert X. Cringely, Computerworld

Function Signature - A function signature is a function prototype other than the return type - the name, the parameter list, and the keyword "const" if used.  The signature of a function is its name and the # and type of its parameters.  The signature does not include the return type.  Below is an example of the Cat class overriding the speak() method in Mammal:

//Overriding a base class method in a derived class
#include <iostream.h>

enum BREED { RussianBlue, Persian, Siamese, Tabby, TortoiseShell, Himilayan };

//--------------------------------------------------------------------------------------------------------------------

class Mammal
{
      public:
     
//constructors
      Mammal() { cout << "Mammal constructor...\n"; }
      ~Mammal() { cout << "Mammal destructor...\n"; }

     
//Other methods
      void Speak()const { cout << "Mammal sound!\n"; }
      void Sleep()const { cout << "Sleeping.\n"; }

      protected:
      int itsAge;
      int itsWeight;
};

//--------------------------------------------------------------------------------------------------------------------

class Cat : public Mammal
{
      public:
     
//Constructors
      Cat(){ cout << "Cat constructor...\n"; }
      ~Cat(){ cout << "Cat destructor...\n"; }

     
//Other methods
      void SwishTail() { cout << "Cat is angry...\n"; }
      void ChaseMice() { cout << "Chasing mice...\n"; }
      void Speak()const { cout << "Meow!\n"; }

      private:
      BREED itsBreed;
};

//--------------------------------------------------------------------------------------------------------------------

int main()
{
    Mammal SmallAnimal;
    Cat Felix;
    SmallAnimal.Speak();
    Felix.Speak();

    return 0;
}
Output:
Mammal constructor . . .
Mammal constructor . . .
Cat constructor . . .
Mammal sound!
 
Meow!
Cat destructor . . .
Mammal destructor . . .
Mammal destructor . . .

In this example, the Cat class overrides the speak() method defined in its base class, Mammal, causing Cat objects to say "Meow!" instead of the base class's "Mammal sound".   In this way, the Cat class Speak() method is said to be "overriding" the Mammal class Speak() method.  In this way, we can give methods that perform similar functions the same name and they will "do the right thing", based on which derived class uses that method.  At this point, some people confuse overloading with overriding, so let's review:

Overloading vs. Overriding

  • When you overload a method, you create more than 1 method with the same name, but DIFFERENT signatures.
  • When you override a method, you create a method in a derived class with the same name as a method in the
    base class, and with the SAME signature (argument and return type).

Hiding the base class method - Hiding a base class method through overriding can cause unexpected problems.  If the Mammal class has a method called Move() that is overloaded, and the Cat class overrides that method, the Cat method will hide all the Mammal methods with that name.  If Mammal class overloads Move() as 3 methods - 1=takes no parameters, 2=takes an int, 3=takes int and a direction,  and the Cat class overrides only the Move() method which takes no parameters, it will not be easy to access the other 2 methods using a Cat object.  Example:

//Hiding methods
#include <iostream.h>

enum BREED { RussianBlue, Persian, Siamese, Tabby, TortoiseShell, Himilayan };

//--------------------------------------------------------------------------------------------------------------------

class Mammal
{
      public:
     
//Constructor and destructor
      Mammal() { cout << "Mammal constructor...\n"; }
      ~Mammal() { cout << "Mammal destructor...\n"; }

    
 //Overloaded Move() methods
      void Move() const { cout << "Mammal move one step\n"; }

      void Move(int distance) const 
      { cout << "Mammal move " << distance <<" _steps.\n"; }

      void Move(int distance, char Direction) const
      { cout << "Mammal moving to the " << Direction << ".";}

      protected:
      int itsAge;
      int itsWeight;
};

//--------------------------------------------------------------------------------------------------------------------

class Cat : public Mammal
{
      public:
     
//Constructor and Destructor
      Cat(){ cout << "Cat constructor...\n"; }
      ~Cat(){ cout << "Cat destructor...\n"; }
 
      
      
 //Other methods
      void SwishTail() { cout << "Cat is angry...\n"; }
      void ChaseMice() { cout << "Chasing mice...\n"; }
      void Speak()const { cout << "Meow!\n"; }

        //You may receive a compiler warning that you are hiding a function!
      void Move() const { cout << "Cat move 5 steps.\n"; }

      private:
      BREED itsBreed;
};

//--------------------------------------------------------------------------------------------------------------------

int main()
{
       Mammal SmallAnimal;

       Cat Morris;

      
//Call Mammal's Move() methods
       SmallAnimal.Move();
       SmallAnimal.Move(2);

      
//Call the Cat class Move() method that overrides the Mammal class Move() with no parameters
       Morris.Move();

      
//The line below will produce an error since nothing overrides the Mammal class methods that take parameters
       //Morris.Move(10);

       return
0;

}

Output:
Mammal move one step
Mammal move two steps.
Cat move 5 steps.


In the example above, the Mammal class declares three overloaded Move() methods.  In the derived Cat class, the version of Move() with no parameters from the base class, Mammal, is overridden with a method specific to Cat objects rather than Mammals.  The next to the last line,
Morris.Move(10); has to be commented out, it will cause a compile-time error.  The Cat class could have called the Move(int) method if it had not overridden the default Mammal class version of Move() without parameters.  However, now that the Cat class has done so, it must override both Move() methods if it wants to use both.  Remember:  if you supply any constructor, the compiler will no longer provide the default constructor. 

Important Note:  It is a common mistake to hide a base class method when you intend to override it.  This is usually accomplished by forgetting to include the keyword "
const".  The keyword "const" is a part of the signature, and leaving it off changes the signature and hides the method rather than overriding it.  Remember that methods being overridden must possess the SAME signature.

Calling the base method - By explicitly calling the base method, you can work around this.  If you overload the base method, you can still call it by fully qualifying the name of the method.  You do this by writing the base name followed by 2 colons and then the method name.  Example:

DerivedClassObject.Mammal::Move();

We could rewrite the last few lines of the program above so that is would compile correctly.  Example:

// . . . (use the same code as in the example above)

int main()
{
       Mammal SmallAnimal;

       Cat Morris;

      
//Call Mammal's Move() methods
       SmallAnimal.Move();
       SmallAnimal.Move(2);

      
//Call the Cat class Move() method that overrides the Mammal class Move() with no parameters
       Morris.Move();

      
       Morris.Mammal::Move(10);

       return
0;

}

Output:
Mammal move 2 steps.
Mammal move 10 steps.

...

Note:  The programmer wanted to invoke Move(int) on the Cat object, but had a problem.  The Cat class overrides the Move() method with no parameters, but it does not overload it.  Neither does the Cat class provide a version of Move() that takes an int, thus overriding the Mammal class method that takes an int parameter.  This is solved by the explicit call to the base class Move(int) method on the last few lines.

Things to Remember:
1) DO - extend the functionality of classes by deriving methods and data members from the base class.
2) DO - change behavior of functions in derived classes by overriding their base class methods as appropriate.
3) DON'T - hide a base class function by changing the function signature without realizing it.  A common mistake is removing "const".



©2004 C. Germany