Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!brunix!sdm From: sdm@cs.brown.edu (Scott Meyers) Newsgroups: comp.lang.c++ Subject: Re: Faulty Ambiguity Detection with Virtual Bases Message-ID: <54893@brunix.UUCP> Date: 30 Oct 90 22:17:19 GMT References: <54733@brunix.UUCP> <58641@microsoft.UUCP> Sender: news@brunix.UUCP Reply-To: sdm@cs.brown.edu (Scott Meyers) Organization: Brown University Department of Computer Science Lines: 53 In article <54733@brunix.UUCP> I wrote: | class VBase { | public: | virtual void foo() = 0; | }; | | class Middle1: virtual public VBase { | public: | virtual void foo(); | }; | | class Middle2: virtual public VBase { | public: | virtual void foo(); | }; | | class Bottom: public Middle1, public Middle2 { | }; In article <58641@microsoft.UUCP> ilanc@microsoft.UUCP (Ilan CARON) writes: | This definition is in error since there is only *one* virtual function | table slot in VBase's vft for function foo() -- hence when creating an | instance of Bottom (which has only *one* embedded instance of VBase | because it's derived from virtually), the compiler can't know which | overriding function, Middle1::foo() or Middle2::foo(), to prefer. C++ | has no rules for resolving this particular ambiguity (note that | dominance is irrelevant here). (Hence instances of Bottom can't be created, | hence the definition is in error). What you say is true, but I claim this is a rationalization for a compiler error, not an explanation as to why the code itself is wrong. (Perhaps the code is wrong, but I'd like to see a reference to the ARM where it says it's wrong.) VBase::foo is pure virtual, which means it should never be called through the vtable; the ARM explicitly says the program behavior is undefined if that ever happens (p. 215). (In cfront 2.0 such a call would result in a runtime error.) So where foo's slot in VBase's vtable points makes no difference -- the pointer should never be used (which means it could be optimized out of existence). It also means that there can never be an object of type VBase, only objects of classes derived from VBase, and foo must be defined in those classes, so VBase::foo can't be called via a reference/pointer to a VBAse. When a Bottom object is created, the vtables for both Middle1 and Middle2 are used, and then there's no problem with space in the vtable. And of course the ambiguity on a call to foo still exists. So I'm unconvinced, I still think this is a compiler error. Am I still overlooking something? Scott sdm@cs.brown.edu