Removing data member from virtual base causes wrong member function to be called
Trent Apted
tapted@gmail.com
Tue Jun 5 08:24:00 GMT 2007
On 6/5/07, Brian Dessent <brian@dessent.net> wrote:
> Trent Apted wrote:
>
> > static void* make_image() {
> > return new Image();
> > }
> >
> > int main() {
> > static_cast<Event*>(make_image())->trigger();
> > return 0;
> > }
> >
> > [...]
> >
> > Can anyone tell me what's going on?
>
> I think you're invoking undefined behavior because you can't use
> static_cast to downcast a pointer like that in the face of virtual
> inheritance. You have to use dynamic_cast. I don't really understand
> why you're intentionally obscuring things with the void* business,
A good point -- I had thought it necessary, as I am pushing things of
type SDL_UserEvent into the SDL event queue -- a C interface,
requiring void*. However, you've made me think about it and clued me
in on a different strategy -- instead casting the Event* to a void* in
the struct, I can convert some simpler struct to void* that just holds
an Event* data member. Thanks!
Although, I now have to create 2 objects for each event using new
(unless I assume sizeof(EventHandle) == sizeof(void*) and do some
reinterpret_cast ing). i.e. it becomes:
static void* make_image() {
EventHandle *eh = new EventHandle;
eh->ref = new Image();
return eh;
}
int main() {
static_cast<EventHandle*>(make_image())->ref->trigger();
return 0;
}
this seems to work.
> but if you change it to "dynamic_cast<Event*>((Image
> *)make_image())->trigger()" you get the desired behavior.
Unfortunately, I can't do this, because the code that calls trigger()
doesn't know anything about Image -- only Events (make_image is
potentially any function that returns something derived from Event) --
and I can't dynamic_cast with a void*, until it has some info about a
parent type.
> The fact that
> the undefined behavior just happens to depend on the layout of Resource
> is incidental.
I had hoped virtual inheritance might remove the conflict between
layout/order of the multiple bases. Indeed, it seems to, but only when
there is a data member, which makes me think something else might be
at work here..
A warning might also be nice -- "implicit cast to void* from type with
virtual bases may cause undefined behaviour" -- but I thought I'd make
sure I'm not missing something obvious before bugging the devs...
*laments the hours spent debugging* ;-)
- Trent.
More information about the Gcc-help
mailing list