Re: inheritance doesn't works as expected
Tony Johansson wrote:[color=blue]
> I have some class definition and a main below.
> This is a strange problem.[/color]
There is nothing strange about it. And there is no problem. The program
behaves _absolutely_ according to language rules.
[color=blue]
> When cout is executing in the for loop below locating in main I get this
> print out on the screen
> Bird eats Bird food
> Cat eats Birds
> for(int i = 0; i<sizeof p/sizeof *p; i++)
> cout << p[i]->type() << " eats " << p[i]->eats()->foodType() << endl;
> The strange thing is that it doesn't matter what return type I have on the
> eats method I always get
> the same answer which is the same as above.
>
> I mean these two gives the same output for class Bird when foodType() is
> called in the for loop
> BirdFood* eats()
> PetFood* eats()[/color]
Since 'BirdFood' is a derived class of 'PetFood', a pointer to it is
"covariant" to the pointer its base.
[color=blue]
> and these two gives the same output for class Cat when foodType() is called
> in the for loop
> CatFood* eats()
> PetFood* eats()[/color]
Same thing.
In both cases, 'eats' in the derived class is the overrider for the base
class' function 'eats'.
The return value type comes into play if you call your function through
a pointer or a reference of either the base class or the derived class.
That's the main reason to have covariant return value types.
[color=blue]
> Just to try to understand this I removed the virtual for this foodType
> method in class PetFood.[/color]
So, you disabled polymorphism. Now, 'BirdFood' or 'CatFood' are not
polymorphic types any longer. When 'eats' returns a pointer to 'PetFood',
that's how the object is treated. A call to 'foodType' always resolves
into 'PetFood::foodType'.
If you keep 'virtual', then the call will be resolved _polymorphically_,
according to the type with which the object (pointed to by 'PetFood*')
was _constructed_. In case of 'BirdFood' 'BirdFood::foodType' is called,
in case of 'CatFood' 'CatFood::foodType'.
[color=blue]
> Now I always get the same output which is
> Bird eats Pet food
> Cat eats Pet food.
> it doesn't matter if I have
> CatFood* eats()
> or
> PetFood* eats()
> In class Cat.[/color]
Yes, it doesn't matter. The returned pointer is of type 'PetFood*',
since you call it through a _pointer_to_Pet_. Had you called 'eats'
through a pointer to 'Cat', you'd get 'CatFood*' (if 'eats' had been
declared to have covariant return value types).
[color=blue]
> I mean if I don't use virtual I will be using the static type and not the
> dynamic type.[/color]
Right.
[color=blue]
> This would mean that if I return CatFood* eats()
> I would be calling foodType in class CatFood and not in class PetFood.[/color]
No. The return value type of Pet::eats is not CatFood*, it's PetFood*.
You would only be calling 'CatFood::foodType' _iff_ the function is
virtual.
[color=blue]
> [...][/color]
V |