472,804 Members | 1,611 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Inheritance guidelines.

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
5 1744
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Anuj P Shah | last post by:
Hi, I am using multiple implementation inheritance in one of my designs, and it seems i am having some kind of a vtable problem when accessing functions. The problem is like so: class E...
4
by: Alex Hunsley | last post by:
I've seen a few discussion about the use of 'super' in Python, including the opinion that 'super' should only be used to solve inheritance diamond problem. (And that a constructor that wants to...
0
by: JKJ | last post by:
I'm not an OOP guru, but I would say ". . .not necessarily" What if the base class and derived classes are internal? Then the base class has to be within the same assembly to be inherited from. ...
2
by: Andy Meyer | last post by:
Hi all, I'm converting some C++ Controls to C# and there's one big thing, that I can't solve: class CControlEx { int nDescriptionID; CString strDescription;
45
by: Ben Blank | last post by:
I'm writing a family of classes which all inherit most of their methods and code (including constructors) from a single base class. When attempting to instance one of the derived classes using...
5
by: Invalidlastname | last post by:
Hi, I just read the pattern "Design and Implementation Guidelines for Web Clients" from MSDN. Here is my question. In chapter 3,...
10
by: Kalim Julia | last post by:
Public Class RichBigDaddy Public Sub PlayPolo() Trace.WriteLine("RichBigDaddy::PlayPolo") End Sub End Class Public Class TrustFundSnob Inherits RichBigDaddy Public Sub PlayPolo()...
2
by: Kay Schluehr | last post by:
The problem of unintended inheritance is typical for OO frameworks and can be explained as follows. Given a class Foo implemented by Alice and a derived class Bar of Foo implemented by Bob. Bar...
26
by: David | last post by:
Hi all, I am really new in C++. I met a problem. Could someone help me? I have a base class: class a { protected: int b; public:
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth

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.