473,768 Members | 2,322 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Multiple and virtual inheritance, and downcasting

Hi,

I've got a minor casting issue which I need to check about (marked // <--).
I was trying to do a static_cast on it (which didn't work, though I'm not
sure why this should be the case?) I also tried reinterpret_cas t (which is
clearly an exceedingly dodgy thing to do; it worked, but I'm not sure
whether it should have worked, or whether (the more likely scenario) it was
just coincidence?) Finally, after a bit of trawling through the FAQ, I
found:

"[25.13] What special considerations do I need to know about when I use a
class that uses virtual inheritance?
No C-style downcasts; use dynamic_cast instead.

(Rest to be written.)"

Having read that, I think the actual solution to the problem is fairly clear
(use dynamic_cast), but I'm curious to know why it's necessary there (and
whether reinterpret_cas t would actually work). This is probably going to be
an example of premature optimization, but this is a (clearly very basic)
testbed for an events subsystem in my engine, and I'm expecting there to be
lots of events around at once, hence if the (albeit slight) overhead of
dynamic_cast could be avoided by using reinterpret_cas t (the loss of a
safety net is not that much of an issue here), that would be preferable.
Obviously, if dynamic_cast is the only (defined :-)) way to go, so be it.

#include <iostream>

class EventBase
{
protected:
int m_flags;
public:
enum // event flags
{
EF_AUDIBLE = 1,
EF_VISIBLE = 2
};

EventBase()
: m_flags(0)
{}

virtual ~EventBase() {}

int flags() const
{
return m_flags;
}
};

class EventAudible : virtual public EventBase
{
public:
EventAudible()
{
m_flags |= EF_AUDIBLE;
}

void do_audible_thin g()
{
std::cout << "audible thing\n";
}
};

class EventVisible : virtual public EventBase
{
public:
EventVisible()
{
m_flags |= EF_VISIBLE;
}

void do_visible_thin g()
{
std::cout << "visible thing\n";
}
};

class EventPlayerFire sWeapon : public EventAudible, public EventVisible
{
};

int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
int flags = pBase->flags();
std::cout << flags << '\n';
if(flags & EventBase::EF_A UDIBLE)
{
EventAudible *p = dynamic_cast<Ev entAudible*>(pB ase); // <--
p->do_audible_thi ng();
}
//...
delete pBase;

return 0;
}

TIA,

Stuart.

P.S. I welcome any and all comments on the design itself - if it's bad, I'd
rather know now :-)
P.P.S. There are a couple of obvious placeholder functions in the above
design; in the actual thing, there would instead be things like:

class EventAudible
{
//...
virtual int magnitude() const; // used by the event manager to
determine the radius of sphere within which the sound is audible, in order
to notify nearby entities
//...
};

In other words, the above cast will be necessary in the final design as it
stands at the moment.
Jul 19 '05 #1
6 6485
"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bi******** *****@news.t-online.com...
Stuart Golodetz wrote:
Hi,

I've got a minor casting issue which I need to check about (marked //
<--). I was trying to do a static_cast on it (which didn't work,
though I'm not sure why this should be the case?) I also tried
reinterpret_cas t (which is clearly an exceedingly dodgy thing to do;
it worked, but I'm not sure whether it should have worked, or whether
(the more likely scenario) it was just coincidence?)


It was just coincidence.


Ok, won't be using that then... :-)
Having read that, I think the actual solution to the problem is fairly
clear (use dynamic_cast), but I'm curious to know why it's necessary
there (and whether reinterpret_cas t would actually work). This is
probably going to be an example of premature optimization, but this is
a (clearly very basic) testbed for an events subsystem in my engine,
and I'm expecting there to be lots of events around at once, hence if
the (albeit slight) overhead of dynamic_cast could be avoided by using
reinterpret_cas t (the loss of a safety net is not that much of an
issue here), that would be preferable. Obviously, if dynamic_cast is
the only (defined :-)) way to go, so be it.


I think dynamic_cast is the way to go.


Fair enough. Out of interest, why is downcasting with virtual inheritance
only allowed if you use dynamic_cast? Is there an obvious problem with using
static_cast that I'm missing? (Clearly I'm talking about the case where the
cast is valid, i.e. where dynamic_cast would not result in NULL)
int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
int flags = pBase->flags();
std::cout << flags << '\n';
if(flags & EventBase::EF_A UDIBLE)
{
EventAudible *p = dynamic_cast<Ev entAudible*>(pB ase); //
<-- p->do_audible_thi ng();
}


Since you use dynamic_cast anyway, you can leave out your flag and
directly write:

if (EventAudible *p = dynamic_cast<Ev entAudible*>(pB ase))
{
p->do_audible_thi ng();
}


Thanks :-)

Out of interest BTW, roughly what sort of overhead am I incurring by turning
on RTTI? Presumably if it was negligible, it would be turned on by default?
And is turning it on going to slow all my code down, or will only the bit
which uses dynamic_cast be slow (if it's the latter, then it's probably no
big deal)? I know this all sounds a lot like premature optimization, but I
usually find that my code is slow enough without my needing to find new and
innovative ways to make it even slower. :-) I'd just like to know how much
all this is costing me, really.

TIA,

Stuart.
//...
delete pBase;

return 0;
}


TIA,

Stuart.

P.S. I welcome any and all comments on the design itself - if it's
bad, I'd rather know now :-)
P.P.S. There are a couple of obvious placeholder functions in the
above design; in the actual thing, there would instead be things like:

class EventAudible
{
//...
virtual int magnitude() const; // used by the event manager to
determine the radius of sphere within which the sound is audible, in
order to notify nearby entities
//...
};

In other words, the above cast will be necessary in the final design
as it stands at the moment.

Jul 19 '05 #2
Stuart Golodetz wrote:

"[25.13] What special considerations do I need to know about when I use a
class that uses virtual inheritance?
No C-style downcasts; use dynamic_cast instead.

(Rest to be written.)"

Having read that, I think the actual solution to the problem is fairly clear
(use dynamic_cast), but I'm curious to know why it's necessary there (and
whether reinterpret_cas t would actually work).
Internal implementation of classes having virtual base classes is quite
complex. Usually such a virtual base is referenced by a pointer and it
may happen that such a base part is not even contiguous in the memory
with the derived object part.

Hence to make a correct cast to a class with virtual base classes some
runtime information about the actual (dynamic) type of the object being
casted may be required. Only dynamic_cast offers a possibility of
consulting the dynamic object type.

reinterpret_cas t is implementation depended and may fail i.e., when the
address of an object with virtual base is not the same as its base
(think about multiple base classes).
int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
int flags = pBase->flags();
std::cout << flags << '\n';
if(flags & EventBase::EF_A UDIBLE)
{
EventAudible *p = dynamic_cast<Ev entAudible*>(pB ase); // <--
p->do_audible_thi ng();
}
//...
delete pBase;

return 0;
}


Any casts being a standard technique of dealing with a class interface
are not a good idea. Your 'EventBase' class lacks a polymorphic method
like 'handleEvent' that when overriden knows more about its dynamic
object type and performs the right action:

EventBase *pBase = new EventPlayerFire sWeapon(/*some event specific data*/);
pBase->handleEvent( ); // Overriden method calls do_audible_thin g() etc.

So think how to replace all your dynamic type queries with polymorphism
and most likely you will not have to deal with casts at all.
Regards,
Janusz

Jul 19 '05 #3

"Stuart Golodetz" <sg*******@dial .pipex.com> wrote in message
news:3f******** *************@n ews.dial.pipex. com...
| "Rolf Magnus" <ra******@t-online.de> wrote in message
| news:bi******** *****@news.t-online.com...

Hi Stuart.

You are better of avaoiding casts if you can.

Why not use polymorphism, and make use of
implicit conversion(s) through the virtual
mechanism ?.

#include <iostream>

class EventBase
{
protected:
int m_flags;
public:
enum // event flags
{
EF_AUDIBLE = 1,
EF_VISIBLE = 2
};

EventBase()
: m_flags(0)
{}

virtual ~EventBase() {}

int flags() const
{
return m_flags;
}

virtual void CheckCondition( const int& N ) = 0;
};

class EventAudible : virtual public EventBase
{
public:
EventAudible()
{
m_flags |= EF_AUDIBLE;
}

void do_audible_thin g()
{
std::cout << "audible thing\n";
}
};

class EventVisible : virtual public EventBase
{
public:
EventVisible()
{
m_flags |= EF_VISIBLE;
}

void do_visible_thin g()
{
std::cout << "visible thing\n";
}
};

class EventPlayerFire sWeapon : public EventAudible, public EventVisible
{
public:
void CheckCondition( const int& flags )
{
if( flags & EF_AUDIBLE )
do_audible_thin g();
}

};

int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
pBase -> CheckCondition( pBase -> flags() );

delete pBase;

return 0;
}

You get the idea <g>.

Cheers.
Chris Val
Jul 19 '05 #4
"Janusz Szpilewski" <sz******@poczt a.onet.pl> wrote in message
news:bi******** **@news.onet.pl ...
Stuart Golodetz wrote:

"[25.13] What special considerations do I need to know about when I use a class that uses virtual inheritance?
No C-style downcasts; use dynamic_cast instead.

(Rest to be written.)"

Having read that, I think the actual solution to the problem is fairly clear (use dynamic_cast), but I'm curious to know why it's necessary there (and whether reinterpret_cas t would actually work).
Internal implementation of classes having virtual base classes is quite
complex. Usually such a virtual base is referenced by a pointer and it
may happen that such a base part is not even contiguous in the memory
with the derived object part.

Hence to make a correct cast to a class with virtual base classes some
runtime information about the actual (dynamic) type of the object being
casted may be required. Only dynamic_cast offers a possibility of
consulting the dynamic object type.

reinterpret_cas t is implementation depended and may fail i.e., when the
address of an object with virtual base is not the same as its base
(think about multiple base classes).


Thanks, that's the reason I was looking for :-)
int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
int flags = pBase->flags();
std::cout << flags << '\n';
if(flags & EventBase::EF_A UDIBLE)
{
EventAudible *p = dynamic_cast<Ev entAudible*>(pB ase); // <--
p->do_audible_thi ng();
}
//...
delete pBase;

return 0;
}


Any casts being a standard technique of dealing with a class interface
are not a good idea. Your 'EventBase' class lacks a polymorphic method
like 'handleEvent' that when overriden knows more about its dynamic
object type and performs the right action:


True enough, but I have a minor problem, namely that I don't want the event
classes to know anything about how to notify nearby entities that they have
occurred (the event manager does that), because that would mean the event
classes having to know about the level structure. I do on the other hand
have a virtual member function for specifying an action when an event
occurs, e.g. for a water particle hitting lava it might create steam
"particles" . I agree that the casts are messy, but I'm not sure how to get
around the above problem. Casting (especially given that it's going to be
extremely limited, since events are only ever going to be visible or
audible - I'm not sure smellable events would enhance a game that much <g>)
seemed a slightly better option here than introducing extra dependencies,
but I'm not really sure about it. Any advice would be much appreciated.

Cheers,

Stuart.
EventBase *pBase = new EventPlayerFire sWeapon(/*some event specific data*/); pBase->handleEvent( ); // Overriden method calls do_audible_thin g() etc.

So think how to replace all your dynamic type queries with polymorphism
and most likely you will not have to deal with casts at all.
Regards,
Janusz

Jul 19 '05 #5
"Chris ( Val )" <ch******@bigpo nd.com.au> wrote in message
news:bi******** ****@ID-110726.news.uni-berlin.de...

"Stuart Golodetz" <sg*******@dial .pipex.com> wrote in message
news:3f******** *************@n ews.dial.pipex. com...
| "Rolf Magnus" <ra******@t-online.de> wrote in message
| news:bi******** *****@news.t-online.com...

Hi Stuart.

You are better of avaoiding casts if you can.
Agreed :-) There are (just counted) only 7 casts in my current project (of
which four are reinterpret_cas ts in one function loading in a binary file,
one is a static_cast to convert the result of sqrt from double to float, one
is casting (a pointer to the start of) an array of unsigned char to const
char *, and one is casting a GLubyte * to a char *). In a project with well
over 5000 lines of code, that's not many... :-) So in general, I would
certainly steer well clear of this dubious way of doing things. On the other
hand, I'm trying to avoid making my event classes dependent on my level
structure (see my reply to Janusz), which complicates matters a little. Any
ideas for avoiding both casting and the extraneous dependency would be much
appreciated. :-)
Why not use polymorphism, and make use of
implicit conversion(s) through the virtual
mechanism ?.

#include <iostream>

class EventBase
{
protected:
int m_flags;
public:
enum // event flags
{
EF_AUDIBLE = 1,
EF_VISIBLE = 2
};

EventBase()
: m_flags(0)
{}

virtual ~EventBase() {}

int flags() const
{
return m_flags;
}

virtual void CheckCondition( const int& N ) = 0;
};

class EventAudible : virtual public EventBase
{
public:
EventAudible()
{
m_flags |= EF_AUDIBLE;
}

void do_audible_thin g()
{
std::cout << "audible thing\n";
}
};

class EventVisible : virtual public EventBase
{
public:
EventVisible()
{
m_flags |= EF_VISIBLE;
}

void do_visible_thin g()
{
std::cout << "visible thing\n";
}
};

class EventPlayerFire sWeapon : public EventAudible, public EventVisible
{
public:
void CheckCondition( const int& flags )
{
if( flags & EF_AUDIBLE )
do_audible_thin g();
}
Unfortunately, if I do it like this, I'll end up with a bunch of code in
every event class checking whether it's audible or visible, or <blah-ible>.
Ideally, nothing within the event classes themselves should need to know
whether they're audible or visible, it only really matters to the event
manager, which notifies nearby entities when an event occurs. That way, the
event information (what happened, where it happened, how loud it was, what
to do in response to it, etc.) is kept separate from the notification
process. In other words, adding new events becomes a simple matter of
writing a constructor and overloading the response action member function
for each event. Simply deriving an event from EventAudible or EventVisible
ensures that nearby entities are notified appropriately.

To my mind, the above way of doing things seems appealing, but unfortunately
I can't find a (nice) way of doing it without casting. Any thoughts?

Cheers,

Stuart.
};

int main()
{
EventBase *pBase = new EventPlayerFire sWeapon;
pBase -> CheckCondition( pBase -> flags() );

delete pBase;

return 0;
}

You get the idea <g>.

Cheers.
Chris Val

Jul 19 '05 #6

"Stuart Golodetz" <sg*******@dial .pipex.com> wrote in message
news:3f******** *************@n ews.dial.pipex. com...
| "Chris ( Val )" <ch******@bigpo nd.com.au> wrote in message
| news:bi******** ****@ID-110726.news.uni-berlin.de...
| >
| > "Stuart Golodetz" <sg*******@dial .pipex.com> wrote in message
| > news:3f******** *************@n ews.dial.pipex. com...
| > | "Rolf Magnus" <ra******@t-online.de> wrote in message
| > | news:bi******** *****@news.t-online.com...

[snip]

Hi Stuart.

| > class EventPlayerFire sWeapon : public EventAudible, public EventVisible
| > {
| > public:
| > void CheckCondition( const int& flags )
| > {
| > if( flags & EF_AUDIBLE )
| > do_audible_thin g();
| > }
|
| Unfortunately, if I do it like this, I'll end up with a bunch of code in
| every event class checking whether it's audible or visible, or <blah-ible>.
| Ideally, nothing within the event classes themselves should need to know
| whether they're audible or visible, it only really matters to the event
| manager, which notifies nearby entities when an event occurs. That way, the
| event information (what happened, where it happened, how loud it was, what
| to do in response to it, etc.) is kept separate from the notification
| process. In other words, adding new events becomes a simple matter of
| writing a constructor and overloading the response action member function
| for each event. Simply deriving an event from EventAudible or EventVisible
| ensures that nearby entities are notified appropriately.
|
| To my mind, the above way of doing things seems appealing, but unfortunately
| I can't find a (nice) way of doing it without casting. Any thoughts?

Unfortunately, I don't know of any other way to do what you want, and I
still think that a careful design with virtual functions is the best way,
as opposed to downcasting.

But if you're going to downcast, you should at least check that
it succeeded, by checking the return value :-):

if( flags & EventBase::EF_A UDIBLE )
{
EventAudible* p = dynamic_cast<Ev entAudible*>( pBase );

if( p )
p -> do_audible_thin g();
}

Cheers.
Chris Val
Jul 19 '05 #7

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

Similar topics

2
4338
by: Graham Banks | last post by:
Does using multiple inheritance introduce any more performance overhead than single inheritance?
8
3220
by: Shawn Casey | last post by:
Consider the following code: interface IBase { virtual void BaseFunction() = 0; }; interface IDerived : public IBase { virtual void DerivedFunction() = 0;
22
23384
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete examples?
5
2124
by: Neelesh Bodas | last post by:
This might be slightly off-topic. Many books on C++ consider multiple inheritence as an "advanced" concept. Bruce Eckel says in TICPP, volume 2 that "there was (and still is) a lot of disagreement about whether is essential in C++". Are there any disadvantages of using multiple inheritence?
3
2655
by: ernesto | last post by:
Hi everybody I have the following class declarations: class Interface { public: virtual char* getName() const = 0; }; class BaseClass : public Interface {
2
1868
by: Heinz Ketchup | last post by:
Hello, I'm looking to bounce ideas off of anyone, since mainly the idea of using Multiple Virtual Inheritance seems rather nutty. I chalk it up to my lack of C++ Experience. Here is my scenario... I have 5 Derived Classes I have 3 Base Classes
7
3740
by: Adam Nielsen | last post by:
Hi everyone, I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this: Shape | +-- Ellipse | +-- Circle
2
2039
by: Alexander Adam | last post by:
Hi! I got a class structure similar to: class Base_Object { ... some functions ... } class Object: public Base_Object,
3
2554
by: Jess | last post by:
Hello, I've been reading Effective C++ about multiple inheritance, but I still have a few questions. Can someone give me some help please? First, it is said that if virtual inheritance is used, then "the responsibility for initializing a virtual base is borne by the most derived class in the hierarchy". What does it mean? Initializing base class is usually done automatically by the compiler, but a derived class can invoke the base...
0
10017
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9961
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9843
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7384
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6656
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5425
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3932
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3534
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2808
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.