Removing data member from virtual base causes wrong member function to be called

Trent Apted tapted@gmail.com
Tue Jun 5 06:41:00 GMT 2007


I've trawled through mailing list archives, Google and C++ standards
and can find nothing about why this is occurring.. I'm hoping someone
here might be able to help.

A minimal example, with a bit of context, is this:

#include <iostream>
using namespace std;

struct Resource {
    //int dummy;
    virtual void initMenu() {
        cerr << "Resource::initMenu()" << endl;
    }
    virtual ~Resource() {}
};
struct Event {
    virtual void trigger() = 0;
    virtual ~Event() {}
};
struct Image :
public virtual Resource,
public virtual Event {
    virtual void trigger() {
        cerr << "Image::trigger()" << endl;
    }
};

static void* make_image() {
    return new Image();
}

int main() {
    static_cast<Event*>(make_image())->trigger();
    return 0;
}


It started off as an example of why virtual bases are needed, but it
also behaves differently when the data member is removed from the base
class.

The above code prints out "initMenu()" on g++ (3.3.6, 3.4.6, 4.1.0 and
4.2.0) and icc (9.1.049) -- both under Linux. Microsoft's compiler
(2005/VC++8 free and 2003/VC++7 non-free) just "segfaults" (status
access violation) when I try to run the code (under Windows). Clearly,
I "want" it to print out "trigger()".

With g++ I compile with -Wall -Wextra -ansi -pedantic and get no
errors or warnings.

With the 'dummy' member present (uncommented), it prints out
"trigger()" as expected. Note that without dummy, sizeofs for
Resource/Event/Image are 4/4/8, with dummy they are 8/4/12. These
sizes do not change if the inheritance is not virtual. However,
without virtual inheritance, it always prints out 'initMenu()' with or
without the dummy member. (Member functions are virtual in all my
tests).

Can anyone tell me what's going on?

Is this a compiler bug or intentional (i.e. whether or not 'dummy' is
present -- identical behaviour on icc seems to suggest that it is not
a bug in gcc)?

Is virtual inheritance really making the "right" thing happen (at
least when 'dummy' IS present) or is this an accident?


I know there is no "diamond inheritance" here, which is usually
mentioned in the same sentence as "virtual inheritance", but changing
the inheritance to virtual seemed to fix the problem -- but only if
the base has at least one data member. It's that last bit that has me
confused.

Thanks heaps,
  Trent.



More information about the Gcc-help mailing list