473,382 Members | 1,441 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,382 software developers and data experts.

Heavy use of virtual MI


Hi!

I've got some questions regarding heavy use of virtual inheritance.

First, let's see a theoretical situation, where I might feel tempted to
use a lot of virtual inheritance.

Let's suppose, we're creating a little strategy game. In our game,
there are Units. A Unit can be either a Human, or a Vehicle. Obviously,
Human and Vehicle are subclasses of Unit.

Now let's suppose that we'd like to use protocol classes, to separate
interface from implementation as much as possible. So we create a
UnitIntf class, and a UnitImpl derived from it. Likewise, we have
HumanIntf and HumanImpl. HumanIntf, besides inheriting from HumanIntf,
should also inherit from UnitImpl. Our class hierarchy now looks like
this (let's forget about Vehicles for now):

UnitIntf
/ \
UnitImpl HumanIntf
\ /
HumanImpl

Furthermore, let's suppose, that we want to seprate functionality
common to most strategy games from functionality specific to our
current game, so that we may easily reuse the common parts in our next
game (or in another one in parallel development). That is, we want to
create a GameEngine layer, and on top of that, a Game layer. So, in our
Engine, we have Unit and Human, interfaces and implementations. In
Game, we have to introduce some Game-specific stuff on the Unit level,
and then some other game-specific things on the Human level. So we will
need GameUnit and GameHuman classes. If we still stick to the interface
/ implementation separation, then we'll have the following classes and
inheritances:

EngineUnitIntf
EngineUnitImpl: EngineUnitIntf
EngineHumanIntf: EngineUnitIntf
EngineHumanImpl: EngineHumanIntf, EngineUnitImpl
GameUnitIntf: EngineUnitIntf
GameUnitImpl: GameUnitIntf, EngineUnitImpl
GameHumanIntf: GameUnitIntf, EngineHumanImpl
GameHumanImpl: GameHumanIntf, GameUnitImpl, EngineHumanImpl

I won't even try to draw this. (Actually, it would be easy in 3d: it's
a nice cube. On one axis, there's Engine / Game, on the other Unit /
Human, and the third Intf / Impl.)

Such design would make heavy use of virtual inheritance. In fact, _all_
the inheritances should be virtual (at least, if we suppose that Human
may have further subclasses).

Although the hierarchy may seem complicated at first, I think it can be
get used to, and once one's used to it, it can even be convenient to
use.

However, I'm not sure how much run-time overhead this would cause.

How is virtual inheritance typically implemented on current compilers?

Am I overusing inheritance here? What design alternatives are there to
create something similar? What's the performance comparison between
protocol classes vs. the pimpl idiom?

Thanks,

Imre

Jul 1 '06 #1
3 1685
Imre wrote:
I've got some questions regarding heavy use of virtual inheritance.

First, let's see a theoretical situation, where I might feel tempted to
use a lot of virtual inheritance.
What you're describing is not virtual inheritance -- that's something
else entirely. Look it up. What you're describing is inheritance from
abstract classes -- i.e., those with only pure virtual functions
(analogous to Java interfaces).
UnitIntf
/ \
UnitImpl HumanIntf
\ /
HumanImpl

EngineUnitIntf
EngineUnitImpl: EngineUnitIntf
EngineHumanIntf: EngineUnitIntf
EngineHumanImpl: EngineHumanIntf, EngineUnitImpl
GameUnitIntf: EngineUnitIntf
GameUnitImpl: GameUnitIntf, EngineUnitImpl
GameHumanIntf: GameUnitIntf, EngineHumanImpl
GameHumanImpl: GameHumanIntf, GameUnitImpl, EngineHumanImpl

I won't even try to draw this. (Actually, it would be easy in 3d: it's
a nice cube. On one axis, there's Engine / Game, on the other Unit /
Human, and the third Intf / Impl.)
There are some obvious questions to be asked about such a design, on
the face of it. Regardless of your questions about efficiency, there
are OOD reasons not to have a million interfaces and a million levels
of hierarchy in a complex lattice. It's not just that it's difficult
to understand, though that can be part of it. It's inflexible. Many
small interfaces are good, but when you start having things like
parallel inheritance hierarchies of interfaces and implementations, it
really begins to not pay for itself. The poor chump at the bottom of
the hierarchy is tightly coupled to all of its parents and has way too
many responsibilities, as a result of having to support so many
interfaces. Just because something is a single sprite on a screen
doesn't mean that all its behavior need live within a single class.
For example, a Unit may have an x and y position, but the movement code
could be entirely separate, and just update x and y once it's figured
out where to move.
Such design would make heavy use of virtual inheritance. In fact, _all_
the inheritances should be virtual (at least, if we suppose that Human
may have further subclasses).
Subsituting again what you mean for what you said, I'll point out that
in C++, once a member function is virtual, it can never *stop* being
virtual farther down the inheritance chain. This isn't obvious,
because the virtual keyword is optional after the first use. Me, I'd
perhaps prefer if it were mandatory.
Although the hierarchy may seem complicated at first, I think it can be
get used to, and once one's used to it, it can even be convenient to
use.
Any design that you feel you must make excuses for and defend is
unlikely to be a good design. It's not just a question of how hard it
is to use, it's a question of how hard it is to change -- as with any
design.
However, I'm not sure how much run-time overhead this would cause.

How is virtual inheritance typically implemented on current compilers?
The rule of thumb is that every virtual function call costs about as
much as one extra pointer dereference at runtime, compared to a
non-virtual function call. If you want to know more about the
mechanism, STFW for terms like "virtual table," "virtual dispatch."
"dynamic binding," etc.
Am I overusing inheritance here? What design alternatives are there to
create something similar?
Quite possibly you are, yes. PreferCompositionToInheritance and obey
the SingleResponsibilityPrinciple. I made WikiWords out of those
because they're probably pages on c2, and you can go look there for
elaboration.
What's the performance comparison between
protocol classes vs. the pimpl idiom?
I assume by "protocol classes" you mean abstract interfaces. In which
case, this is apples-to-oranges. The two idioms do not solve similar
problems, and so comparing them is meaningless.

Luke

Jul 2 '06 #2

First, thanks for your answers. I've got some more questions though, if
you don't mind.

Luke Meyers wrote:
Imre wrote:
First, let's see a theoretical situation, where I might feel tempted to
use a lot of virtual inheritance.

What you're describing is not virtual inheritance -- that's something
else entirely. Look it up. What you're describing is inheritance from
abstract classes -- i.e., those with only pure virtual functions
(analogous to Java interfaces).
Not neccessarily. Yes, some of the classes involved are abstract base
classes, but there are also some base classes that provide
implementation. For example, GameUnitImpl would be likely to inherit
some implementation from EngineUnitImpl. Also, Human inherits
implementation from Unit.
There are some obvious questions to be asked about such a design, on
the face of it. Regardless of your questions about efficiency, there
are OOD reasons not to have a million interfaces and a million levels
of hierarchy in a complex lattice. It's not just that it's difficult
to understand, though that can be part of it. It's inflexible. Many
small interfaces are good, but when you start having things like
parallel inheritance hierarchies of interfaces and implementations, it
really begins to not pay for itself. The poor chump at the bottom of
the hierarchy is tightly coupled to all of its parents and has way too
many responsibilities, as a result of having to support so many
interfaces. Just because something is a single sprite on a screen
doesn't mean that all its behavior need live within a single class.
For example, a Unit may have an x and y position, but the movement code
could be entirely separate, and just update x and y once it's figured
out where to move.
Yes, I agree with you, and here I'd use some kind of component based
design.

However, the original example was a bit different. I can see how to
factor out the movement code into a separate, contained object, but I
can't see how to do that when inheritance is used to separate the
abstract interface from the implementation (UnitIntf / UnitImpl), or to
separate different layers (EngineUnit / GameUnit).
Maybe the Unit / Human inheritance could be removed, if all units in
the game are instances of Unit, and they differ only in the components
they contain (eg. a vehicle has a WheelManager component added to it,
while a human doesn't), but... it feels a bit, well, unnatural to me.
PreferCompositionToInheritance and obey
the SingleResponsibilityPrinciple.
Generally I try to follow these rules (especially the one about single
responsibilities), but in the original example I'm not sure how I
should do it.

Thanks,

Imre

Jul 3 '06 #3
Imre wrote:
What you're describing is not virtual inheritance -- that's something
else entirely. Look it up. What you're describing is inheritance from
abstract classes -- i.e., those with only pure virtual functions
(analogous to Java interfaces).

Not neccessarily. Yes, some of the classes involved are abstract base
classes, but there are also some base classes that provide
implementation. For example, GameUnitImpl would be likely to inherit
some implementation from EngineUnitImpl. Also, Human inherits
implementation from Unit.
Yes, of course -- the point was that "virtual inheritance" means
something else entirely, and you consistently used that term
incorrectly, so you should look it up and understand it to avoid that
mistake in the future.
However, the original example was a bit different. I can see how to
factor out the movement code into a separate, contained object, but I
can't see how to do that when inheritance is used to separate the
abstract interface from the implementation (UnitIntf / UnitImpl), or to
separate different layers (EngineUnit / GameUnit).
Maybe the Unit / Human inheritance could be removed, if all units in
the game are instances of Unit, and they differ only in the components
they contain (eg. a vehicle has a WheelManager component added to it,
while a human doesn't), but... it feels a bit, well, unnatural to me.
PreferCompositionToInheritance and obey
the SingleResponsibilityPrinciple.

Generally I try to follow these rules (especially the one about single
responsibilities), but in the original example I'm not sure how I
should do it.
It's really impossible to say, since all you ever did was list the
interfaces, not saying anything about the responsibilities involved.
The movement example was my best guess at the sort of thing you might
mean. If you want to know whether you've grouped your responsibilities
appropriately (or rather, not grouped them, but not divided them
either), you'll have to say what they are.

Luke

Jul 3 '06 #4

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

Similar topics

2
by: Ray Paseur | last post by:
My client is a financial services firm with very large email requirements. Hundreds of messages per day both in and out, with attachments in the 1MB to 10MB range. Can anyone suggest a US-based...
0
by: Kayra Otaner | last post by:
Hi all, I want to get your opinions on how to increase available/free memory and performance on a heavy volume database server. I have MySQL 4.0.13 running on RH 7.2 replicated to another RH...
9
by: Jack | last post by:
Hello I have a library of calculationally intensive classes that is used both by a GUI based authoring application and by a simpler non-interactive rendering application. Both of these...
3
by: John Wells | last post by:
A manager friend of mine sent me the following concern. He's preparing to shift to Postgresql from a proprietary DB and 4gl system: ----------- To that end, I've also started studying up on...
4
by: Michiel Alsters | last post by:
Hello everybody, I hope anybody can help me. I'll try to give a brief overview of my problem. I have running a program that performs a heavy calculation. To give the user feedback what the...
10
by: roygon | last post by:
Hello, I have a C# application that runs a relatively complex simulation which, on a typical computer, could take up to 10 seconds. I am now trying to port this application over to ASP.NET so...
6
by: Chris Burnley | last post by:
We're seeing very strange behaviour with db2 under heavy load. We're running our system in GMT and the timezone never changes for British Summer Time. Basically the thing we're doing is (using...
6
by: JimLad | last post by:
Hi, We have a major ASP app that we are in the process of upgrading to ASP.NET 1.1 and probably on to ASP.NET 2.0 in the middle of next year. (We will also be upgrading to SQL2K5 at the same...
25
by: jwrweatherley | last post by:
I'm pretty new to python, but am very happy with it. As well as using it at work I've been using it to solve various puzzles on the Project Euler site - http://projecteuler.net. So far it has not...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.