TITLE: Multiple inheritance and same signature virtual functions JA = jamshid@ses.com (Jamshid Afshar), April 1, 1994 JK = James Kanze [ The sections marked JA?? I think are comments also from Jamshid. I had trouble untangling the posting. -adc ] JA: struct GunFighter { virtual void draw() { cout << "Bang."; /*...*/; } void get_mad() { draw(); } }; struct Image { virtual void draw() { cout << "Pretty"; /*...*/; } }; class Cartoon : public Image, public GunFighter {}; main() { Cartoon c; c.get_mad(); // c.draw(); -- error: ambiguous } JA??: [...] The above program should execute GunFighter::draw(). You should definitely report a compiler bug if it doesn't. g++ 2.5.5 and Cfront 3.0.2 do the right thing. JK: Why should it prefer GunFighter::draw to Image::draw? The fact that the functions are virtual here should not really make a difference, since there is no pointer or reference involved. The compiler *knows* the full type of the object in question. Any decent compiler should give an error. JA: I think you're missing something. When I wrote that the above program should execute GunFighter::draw(), I meant that c.get_mad() is called in main() and it executes GunFighter::draw(). Do you disagree or were you confused by the mentioning of the unrelated ambiguity error? JK: The problem occurs if I have a reference or a pointer to a Cartoon. Should the compiler refuse to generate the call because the function is ambiguous. A class derived from Cartoon may have overridden 'draw', and it would not be ambiguous. This is, I think, the question. Is such a program illegal (requiring a compiler diagnostic), or simply undefined (and may be core dumping on execution). JA: If you have a pointer/reference or an object whose static type is Cartoon, you cannot call draw() because it is ambiguous. If you use a pointer/reference to either base class, you can call draw() and it chooses the draw() that is in that scope. Cartoon sam; sam.draw(); // error: ambiguous GunFighter& gf = sam; gf.draw(); // okay: "bang" JA??: Note, if you happened to define a Cartoon::draw() function, it would override *both* GunFighter::draw() and Image::draw(). I think ARM 10.1.1 and 10.2 discuss this. JK: If I understand the intent of section 10.2, calling 'draw' through a pointer to GunFighter should get GunFighter::draw, and calling through a pointer to Image should get Image::draw. But it is not 100% clear, since there is much reference to `derived::f', which in this case maps to Cartoon::draw. Cartoon::draw is unambiguously ambiguous. JA: I can't point to anything that explicitly says GunFighter::get_mad() would call GunFighter::draw() (as opposed to being undefined), but the ARM never implies that unrelated classes interfere with each others' virtual functions. 10.2: If a class `base' contains a virtual function vf, and a class `derived' derived from it also contains a function vf of the same type, then [...] the derived class function is said to override the base class function. The January WP is a bit clearer -- it uses the word "declares" instead of "contains". I'm not sure what you mean by your last statement that Cartoon::draw is ambiguous. If you mean that calling draw() on a Cartoon object/reference/pointer is an ambiguity error, then I agree. If you mean that declaring a function draw() in Cartoon is ambiguous, then no, I disagree. There's an example of this in 10.8c (commentary). It's basically says: struct A { virtual void f(); }; struct B { virtual void f(); }; struct C : public A, public B { void f(); }; C* pc = new C; B* pb = pc; A* pa = pa; // all the following invoke C::f() pa->f(); pb->f(); pc->f();