473,396 Members | 1,833 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

inheritance doesn't works as expected

Hello Experts!

I have some class definition and a main below.
This is a strange problem.
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()

and these two gives the same output for class Cat when foodType() is called
in the for loop
CatFood* eats()
PetFood* eats()

Just to try to understand this I removed the virtual for this foodType
method in class PetFood.
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.

I mean if I don't use virtual I will be using the static type and not the
dynamic type.
This would mean that if I return CatFood* eats()
I would be calling foodType in class CatFood and not in class PetFood.
//Class definitions
#include <iostream>
#include <string>
using namespace std;

class PetFood
{
public:
string foodType() const
{ return "Pet food"; }
};

class Pet
{
public:
virtual string type() const = 0;
virtual PetFood* eats() = 0;
};

class Bird : public Pet
{
public:
string type() const
{ return "Bird"; }

class BirdFood : public PetFood
{
public:
string foodType() const
{ return "Bird food"; }
};

PetFood* eats()
{ return &bf; }

private:
BirdFood bf;
};

class Cat : public Pet
{
public:
string type() const
{ return "Cat"; }

class CatFood : public PetFood
{
public:
string foodType() const
{ return "Birds"; }
};

CatFood* eats()
{ return &cf; }

private:
CatFood cf;
};

#include <iostream>
#include "pet.h"
using namespace std;
int main()
{
Bird b;
Cat c;
Pet* p[] = {&b, &c};

for(int i = 0; i<sizeof p/sizeof *p; i++)
cout << p[i]->type() << " eats " << p[i]->eats()->foodType() << endl;
return 0;
}

Many thanks

//Tony
Aug 19 '05 #1
2 1193
Tony Johansson wrote:
[snip]

Judging from the number of questions you're posting per day on this
newsgroup, you may want to consider another method of learning. If
you're taking a class, it might be time to talk to your professor about
the things you're asking about on the list. If you're using a book, you
may want to consider getting a new one.

Not to be mean, but these questions all seem like they'd come off a
homework assignment from someone's programming course. Always a few
theory questions and then an problem.

Aug 19 '05 #2
Tony Johansson wrote:
I have some class definition and a main below.
This is a strange problem.
There is nothing strange about it. And there is no problem. The program
behaves _absolutely_ according to language rules.
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()
Since 'BirdFood' is a derived class of 'PetFood', a pointer to it is
"covariant" to the pointer its base.
and these two gives the same output for class Cat when foodType() is called
in the for loop
CatFood* eats()
PetFood* eats()
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.
Just to try to understand this I removed the virtual for this foodType
method in class PetFood.
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'.
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.
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).
I mean if I don't use virtual I will be using the static type and not the
dynamic type.
Right.
This would mean that if I return CatFood* eats()
I would be calling foodType in class CatFood and not in class PetFood.
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.
[...]


V
Aug 19 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
by: Mike Meng | last post by:
hi all, I'm a newbie Python programmer with a C++ brain inside. I have a lightweight framework in which I design a base class and expect user to extend. In other part of the framework, I heavily...
6
by: Brian Jones | last post by:
I'm sure the solution may be obvious, but this problem is driving me mad. The following is my code: class a(object): mastervar = def __init__(self): print 'called a'
2
by: Søren Holstebroe | last post by:
Hi there, I'm having a struggle with GNU g++ (3.3.5) and inheritance of typedefs in STL containers. I'm trying to port some old code I wrote with MS Visual C++ and it looks like there is a...
2
by: Tony Johansson | last post by:
Hello experts! My question is what advantage and disadvantage have public inheritance. The answer that I have to this is that sometimes it is an advantage to let a client have access to...
14
by: Steve Jorgensen | last post by:
Recently, I tried and did a poor job explaining an idea I've had for handling a particular case of implementation inheritance that would be easy and obvious in a fully OOP language, but is not at...
1
by: Zachary Hartnett | last post by:
I was trying to write a routine this morning that would open a given assembly, walk the inheritance tree of classes in the assembly, and provide a list of classes in the assembly that inherit from...
60
by: Shawnk | last post by:
Some Sr. colleges and I have had an on going discussion relative to when and if C# will ever support 'true' multiple inheritance. Relevant to this, I wanted to query the C# community (the...
36
by: Pacific Fox | last post by:
Hi all, haven't posted to this group before, but got an issue I can't work out... and hoping to get some help here ;-) I've got a base object that works fine with named arguments when called...
12
by: not_a_commie | last post by:
What's the technical reason for not allowing structs to be hierarchical? WPF has a nice Point3D struct. I wanted to add some additional constructors to it for converting from my data types.
5
by: Lars Hillebrand | last post by:
Hello, i discovered a weird behaviour if i use templates together with virtual inheritance and method over. I managed to reproduce my problem with a small example: // *********** <code...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.