By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,954 Members | 1,152 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,954 IT Pros & Developers. It's quick & easy.

Inheritance guidelines.

P: n/a
Hi,

While I think I have a reasonable grasp of C++ in general, I've never
really used it more than a convenient C. as such, I'm finding very
basic OO confusing, not so much the concept, but how everything should
be laid out in practice.

One of those is deciding whether or not a class should be inherited
or declared as an object in the class.

note: this isn't isn't a specific problem, just making pseudo code as
an example.

class RootProgramClass : public ConfigClass, public Window
{
}

vs.

class RootProgramClass
{
ConfigClass config;
Window window;
}

How about appropriate use of constructors? something tells me a
constructor taking arguments just to pass onto an inherited classes
constructor, to pass onto the final classes constructor, to initialize
the classes variables, isn't very good design. Are there ways to avoid
this mess and allow the programmer to initialize an double inherited
classes variables neatly.

these are all newbish questions and it shames me to ask them,
unfortunately I'm nothing more than a hobbyist so don't have the
benefit of university level courses, etc.

any resources on good OO design, etc. would be appreciated.
Dec 7 '07 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Victor Bazarov wrote:
The only reason for public inheritance is to extend the class from
which you inherit. For example, you have a generic Window that does
not really do much, only knows how to report its own position, say,
and has a bunch of virtual functions to respond to some system
"messages", then any window you create will probably be descending
from that type... So, according to very early teachings on OOD,
the relationship between your CustomWindow and a generic Windows
exists and it's the "is-a" relationship. CustomWindow "is-a" Window.
Another basic concept of object-oriented design (which can have
exceptions, but is still a good rule-of-thumb) is that a base class is a
more abstract concept than a derived class, which is a more concrete
concept.

The classic example is a class hierarchy related to living organisms.
For example, you can have a class named "Animal" and a class derived
from it called "Dog".
"Animal" is a more abstract concept: It defines the properties which
are common to all animals. "Dog" is a more concrete concept: It defines
all the same properties as "Animal", but besides them it defines
additional properties which are exclusive to dogs. It's thus a more
concrete definition at a conceptual level.
You could also have a class named "Cat", which is derived from
"Animal". It defines a different type of animal, with its own properties.

This nicely follows the "is-a" relationship: A "Dog" is an "Animal", a
"Cat" is an "Animal", but a "Dog" is not a "Cat". They are distinct
classes. A function taking an "Animal" can be given a "Dog" or a "Cat",
but a function taking a "Dog" cannot be given a "Cat".

This also answer the classic OOD problem: If we have circles and
ellipses, should circle be inherited from ellipse, or the other way around.
Maybe circle should be inherited from an ellipse? After all, a circle
*is* an ellipse, just with a constraint. It's a special type of ellipse.
However, if we do that, we encounter problems: For example, an ellipse
has two radiuses, but a circle has only one. Thus a circle does *not*
implement all the properties of an ellipse.
So maybe the ellipse should be inherited from a circle? After all, an
ellipse can be thought as an extension of a circle. However, this also
causes problems: If a function taking a circle asks it for its radius,
what should the ellipse return? The major radius? The minor one? Some
combination? Not good.

The answer is that neither should be inherited from the other. This is
because a circle and an ellipse are at the *same* conceptual level. They
are both drawing primitives. You can't really say that one concept is
more abstract than the other. They are both equally concrete concepts.
Thus inheriting one from the other would be wrong.

The correct solution is to create a more abstract concept which is
common to both circles and ellipses (and other similar drawing
primitives), for example a "DrawingPrimitive" class, and inherit
"Circle" and "Ellipse" from it. Thus a circle *is a* drawing primitive,
and an ellipse *is a* drawing primitive.
Dec 8 '07 #2

P: n/a
On Dec 7, 7:17 pm, Juha Nieminen <nos...@thanks.invalidwrote:
Victor Bazarov wrote:
The only reason for public inheritance is to extend the class from
which you inherit. For example, you have a generic Window that does
not really do much, only knows how to report its own position, say,
and has a bunch of virtual functions to respond to some system
"messages", then any window you create will probably be descending
from that type... So, according to very early teachings on OOD,
the relationship between your CustomWindow and a generic Windows
exists and it's the "is-a" relationship. CustomWindow "is-a" Window.

Another basic concept of object-oriented design (which can have
exceptions, but is still a good rule-of-thumb) is that a base class is a
more abstract concept than a derived class, which is a more concrete
concept.

The classic example is a class hierarchy related to living organisms.
For example, you can have a class named "Animal" and a class derived
from it called "Dog".
"Animal" is a more abstract concept: It defines the properties which
are common to all animals. "Dog" is a more concrete concept: It defines
all the same properties as "Animal", but besides them it defines
additional properties which are exclusive to dogs. It's thus a more
concrete definition at a conceptual level.
You could also have a class named "Cat", which is derived from
"Animal". It defines a different type of animal, with its own properties.

This nicely follows the "is-a" relationship: A "Dog" is an "Animal", a
"Cat" is an "Animal", but a "Dog" is not a "Cat". They are distinct
classes. A function taking an "Animal" can be given a "Dog" or a "Cat",
but a function taking a "Dog" cannot be given a "Cat".

This also answer the classic OOD problem: If we have circles and
ellipses, should circle be inherited from ellipse, or the other way around.
Maybe circle should be inherited from an ellipse? After all, a circle
*is* an ellipse, just with a constraint. It's a special type of ellipse.
However, if we do that, we encounter problems: For example, an ellipse
has two radiuses, but a circle has only one. Thus a circle does *not*
implement all the properties of an ellipse.
So maybe the ellipse should be inherited from a circle? After all, an
ellipse can be thought as an extension of a circle. However, this also
causes problems: If a function taking a circle asks it for its radius,
what should the ellipse return? The major radius? The minor one? Some
combination? Not good.

The answer is that neither should be inherited from the other. This is
because a circle and an ellipse are at the *same* conceptual level. They
are both drawing primitives. You can't really say that one concept is
more abstract than the other. They are both equally concrete concepts.
Thus inheriting one from the other would be wrong.

The correct solution is to create a more abstract concept which is
common to both circles and ellipses (and other similar drawing
primitives), for example a "DrawingPrimitive" class, and inherit
"Circle" and "Ellipse" from it. Thus a circle *is a* drawing primitive,
and an ellipse *is a* drawing primitive.
Yeah, the is-a has-a relationships seem blatantly obvious in some
examples, such as Dog : Animal
Civic : Car, a car isn't an engine, but it has one, so Car should
contain engine rather than inherit from it. Sometimes it just doesn't
seem so clear to me though. I'm starting to think though that my
problem isn't lack of understanding in regards to composition vs.
inheritance, which seems pretty straightforward, but the areas in
which I'm programming.

For a better example than the one I originally provided consider this:
You have a Game class, an Engine class, and a Window class.

The Window class is responsible for say, resizing, OpenGL
initialization, and updating the window. The Engine class is
responsible for monitoring input and dispatches events to virtual
functions which are overridden in the Game class and tied to game
logic, like updating position of objects, etc. The only way I can
think of making this work is Game inheriting Engine inheriting
Window. We come back to is-a and has-a.

Should Engine have a Window? or should Engine be an extension of
Window? Should a Game class have an Engine? or should a Game class
been an extension of an Engine?

extension of _x is the only way I could conceive of it working, but it
doesn't quite seem right. Perhaps I should be asking these questions
on a game development group or forum. ;-)
Dec 8 '07 #3

P: n/a
su**********@yahoo.ca wrote:
[..] I'm starting to think though that my
problem isn't lack of understanding in regards to composition vs.
inheritance, which seems pretty straightforward, but the areas in
which I'm programming.
It seems that once the relationship has been established, you can
tell whether it's logical or not, but when you have a set of your
own types/concepts, figuring out the relationship between them is
a challenge.
For a better example than the one I originally provided consider this:
You have a Game class, an Engine class, and a Window class.
Is "Model/View/Controller" pattern something you'd be intersted in?
The pattern is very common and many books have been written around
it.
The Window class is responsible for say, resizing, OpenGL
initialization, and updating the window. The Engine class is
responsible for monitoring input and dispatches events to virtual
functions which are overridden in the Game class and tied to game
logic, like updating position of objects, etc. The only way I can
think of making this work is Game inheriting Engine inheriting
Window. We come back to is-a and has-a.

Should Engine have a Window? or should Engine be an extension of
Window? Should a Game class have an Engine? or should a Game class
been an extension of an Engine?
Start by reading/thinking about MVC layout of your program. What
is the view? A window. What does it do? What is the role of the
view in that architecture? What is playing the controller? What
is the model?

The main question you need to ask (and answer) is "what does it
do", about each of the pieces in your application. Try not to
start with "I have an Engine, a Game, and a Window -- who owns
what and who is what?" Those are the wrong questions to ask.
Why do you have an Engine? Well, you probably need one (or more)
to make your application do something, but is it (or are they)
really the top-level element(s)?

Design from bottom up is difficult if not wrong.
extension of _x is the only way I could conceive of it working, but it
doesn't quite seem right. Perhaps I should be asking these questions
on a game development group or forum. ;-)
The more venues you visit, the more information you'll collect,
and that's A GOOD THING(tm). Of course, developing a game is
not really different from developing a CAD system or a Banking
system. All have data, all have UI. All have components you
get from 3rd parties (engines, libraries). But don't start
with "I have a brick and a board, what house do I build from
those?" Start by asking what house you want, what should it
have, and then arrive to bricks and boards you may need to
accomplish your goals.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 8 '07 #4

P: n/a
Alf P. Steinbach wrote:
* Juha Nieminen:
>[About circles and ellipses] The answer is that neither should be
inherited from the other. This is
because a circle and an ellipse are at the *same* conceptual level.

Generally, when that's the case, the person's concepts are flawed :-).

E.g., a constant circle Is-A constant ellipse (the general relationship
is a bit more complicated).
IMO that's the wrong usage of the "is-a" relationship. IMO "is-a" is
more related to abstract/concrete than to human language. Even though
you can *say* "thing A is a thing B", that doesn't mean that B is a more
abstract concept than A. IMO the "is-a" relation should always be
applied with levels of abstraction.

An ellipse is not a more abstract concept than a circle. They are both
equally concrete concepts. (And in fact, in a way, one could even argue
that an ellipse is slightly more concrete than a circle because the
ellipse has more information in it than a circle.)

I would say that from OO point of view a circle is *not* an ellipse,
even if in mathematics you could say that it is. However, OOD is a
different field from mathematics.
In C++ this can be expressed via interfaces or via implicit conversion.
Even if you can, that doesn't mean you should.
> The correct solution is to create a more abstract concept which is
common to both circles and ellipses (and other similar drawing
primitives), for example a "DrawingPrimitive" class, and inherit
"Circle" and "Ellipse" from it.

Sorry, but there's no general "the" correct solution.
You are welcome to suggest a better solution from OOD point of view.
Dec 10 '07 #5

P: n/a
su**********@yahoo.ca wrote:
The Window class is responsible for say, resizing, OpenGL
initialization, and updating the window. The Engine class is
responsible for monitoring input and dispatches events to virtual
functions which are overridden in the Game class and tied to game
logic, like updating position of objects, etc. The only way I can
think of making this work is Game inheriting Engine inheriting
Window. We come back to is-a and has-a.
Actually that sounds to me like a clear case where you should use a
callback mechanism.

Your game engine class is not a window, it's an event listener. Thus
it should be inherited from an event listener interface/class. When you
instantiate your Window class, you give a pointer/reference to your game
engine (which "is-a" event listener). The Window instance just sees a
pointer/reference of type event listener and calls its virtual functions
when events happen.

(There are advantages in doing it like this. For example, you can
change the event listener which the Window instance dispatches the
events to on the fly. You could even have more than one event listener
which receive events from the same Window instance.)
Dec 10 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.