Path: utzoo!mnetor!tmsoft!torsqnt!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!microsoft!jimad From: jimad@microsoft.UUCP (Jim ADCOCK) Newsgroups: comp.lang.c++ Subject: Re: multiple inheritance bug Keywords: multiple inheritance, virtual base classes Message-ID: <70547@microsoft.UUCP> Date: 7 Feb 91 21:36:17 GMT References: <3553@island.COM> <9592@dog.ee.lbl.gov> Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 89 In article <9592@dog.ee.lbl.gov> beard@ux5.lbl.gov (Patrick C Beard) writes: |In article <3553@island.COM> lars@island.COM (Lars Nyman) writes: |# |#I have a problem with multiple inheritance using virtual base classes, and |#suspect it's a bug in the C++ compiler. | |Don't be so quick to call this a bug. It's actually a feature. C++ does |not officially support the calling of virtual functions from a constructor. |The reason? If you are in the base class constructor of a derived class, |and you call a virtual function, if it called a function that is defined in |the derived class, that function would be passed a pointer to an incompletely |constructed derived object. I mainly agree with Patrick -- but -- C++ *does* officially support the calling of virtual functions from a constructor. ARM page 294: "Member functions may be called in constructors and destructors. This implies that virtual functions may be called (directly or indirectly). The function called will be the one defined in the constructor's (or destructor's) own class or its bases, but *not* in any function overriding it in a derived class....." The reason for this behavior is very simple. When in the base class constructor, the object IS a base class object. The object does not become a derived class object until the derived class constructor begins to run on it to make it a derived class object. The object then IS a derived object until the mostderived class constructor starts to run on it, making it a mostderived class object. Thus, in any constructor, the object being constructed IS exactly the type of the constructor's class -- at least while in that constructor. Destructors work exactly the same way. Thus, virtual functions in constructors and destructors *are* officially supported by the language, and work exactly the same way in constructors and destructors as they work anywhere else in the language. Rather, the problem is that many people don't understand that the *type* of an object is dynamically changing as the object is run through each phase of construction and destruction. Perhaps this example will make things more clear: extern "C" { #include } class base { public: virtual void whatami() { printf("I'm a base.\n"); } base() { printf("In the base constructor "); whatami(); } ~base() { printf("In the base destructor "); whatami(); } }; class derived : public base { public: /* virtual void whatami() { printf("I'm a derived.\n"); } */ derived() { printf("In the derived constructor "); whatami(); } ~derived() { printf("In the derived destructor "); whatami(); } }; class mostderived : public derived { public: virtual void whatami() { printf("I'm a mostderived.\n"); } mostderived() { printf("In the mostderived constructor "); whatami(); } ~mostderived() { printf("In the mostderived destructor "); whatami(); } }; main() { mostderived object; return 0; } ---- should print: In the base constructor I'm a base. In the derived constructor I'm a derived. In the mostderived constructor I'm a mostderived. In the mostderived destructor I'm a mostderived. In the derived destructor I'm a derived. In the base destructor I'm a base. If it doesn't -- call your compiler vendor and complain.