A Dog object has access to all the member functions in class Mammal, as well as to any member functions, such as WagTail(), that the declaration of the Dog class might add. It can also override a base class function. Overriding a function means 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.
When a derived class creates a member function with the same return type and signature as a member function in the base class, but with a new implementation, it is said to be overriding that method. |
When you override a function, it must agree in return type and in signature with the function in the base class. The signature is the function prototype other than the return type: that is, the name, the parameter list, and the keyword const, if used.
The signature of a function is its name, as well as the number and type of its parameters. The signature does not include the return type. |
Listing 16.5 illustrates what happens if the Dog class overrides the speak() method in Mammal. To save room, the accessor functions have been left out of these classes.
Mammal constructor... Mammal constructor... Dog constructor... Mammal sound! Woof! Dog destructor... Mammal destructor... Mammal destructor...
On line 41, the Mammal object calls its Speak() method; then on line 42 the Dog object calls its Speak() method. The output reflects that the correct methods were called. Finally, the two objects go out of scope, and the destructors are called.
These terms are similar, and they do similar things. When you overload a method, you create more than one method with the same name but with 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.
In the previous listing, the Dog class's method Speak() hides the base class's method. This is just what is wanted, but it can have unexpected results. If Mammal has a Move() method that is overloaded, and Dog overrides that method, the Dog method will hide all the Mammal methods with that name.
If Mammal overloads Move() as three methods—one that takes no parameters, one that takes an integer, and one that takes an integer and a direction—and Dog overrides just the Move() method, which takes no parameters, it will not be easy to access the other two methods using a Dog object. Listing 16.6 illustrates this problem.
Line 28, however, is commented out, as it causes a compile-time error. Although the Dog class could have called the Move(int) method if it had not overridden the version of Move() without parameters, now that it has done so it must override both if it wants to use both. This is reminiscent of the rule that states if you supply any constructor, the compiler will no longer supply a default constructor.
It is a common mistake to hide a base class method, when you intend to override it, by forgetting to include the keyword const. const is part of the signature, and leaving it off changes the signature and thus hides the method rather than overriding it.
If you have overridden the base method, it is still possible to call it by fully qualifying the name of the method. You do this by writing the base name, followed by two colons and then the method name. For example:
Mammal::Move()
It would have been possible to rewrite line 28 in Listing 16.6 so that it would compile:
28: fido.Mammal::Move(10);
This calls the Mammal method explicitly. Listing 16.7 fully illustrates this idea.
On line 29, a Mammal, bigAnimal, is created; and on line 30, a Dog, Fido, is created. The method call on line 31 invokes the Move() method of Mammal, which takes an int. |
The programmer wants to invoke Move(int) on the Dog object, but has a problem. Dog overrides the Move() method, but does not overload it and does not provide a version that takes an int. This is solved by the explicit call to the base class Move(int) method on line 32.
3.16.48.181