Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!dali.cs.montana.edu!uakari.primate.wisc.edu!samsung!uunet!world!wmm From: wmm@world.std.com (William M Miller) Newsgroups: comp.lang.c++ Subject: Re: Reference problem?? Message-ID: <1991Apr28.231218.1978@world.std.com> Date: 28 Apr 91 23:12:18 GMT References: Distribution: comp Organization: Glockenspiel, Ltd. Lines: 69 cimshop!davidm@uunet.UU.NET (David S. Masterson) writes: > [long example deleted] > I don't understand why the cast is necessary. Without the cast, Oregon C++, > Turbo C++, and G++ tells me something like: > > Warning: Lvalue coerced into temporary to initialize reference type > > Can anyone explain why? The deleted example essentially boils down to something like: class Base { }; class Derived: public Base { }; void f(Base*&); void g() { Derived* p = new Derived; f((Base*) p); } This question comes up fairly regularly. To paraphrase E&S section 4.7, you can convert an X& to a Y& without a cast if and only if Y is an unambiguous accessible base class of X. In this example, Base stands in that relationship to Derived, but Base* and Derived* do not -- pointers are not classes! This distinction is of more than academic concern. Consider the following slightly-elaborated example (using structs to allow access while keeping the line count down): struct Base1 { int i; }; struct Base2 { }; struct Derived: Base1, Base2 { }; Base2 b2; void f(Base2*& b2p) { b2p = &b2; } int main() { Derived* dp; g(dp); // Illegal -- for example purposes only dp->i = 5; } If you run this program, you will scribble on the memory immediately preceding the "b2" object in static storage. I hope this example illustrates why a Derived* is not compatible with a Base*&. The message you are getting is the same one you get if you try to do something like int i; double* dr = i; The value of "i" will be converted into a double and the reference will be initialized with that temporary, not with "i". In the original example, the Derived* was converted into a Base* and the reference argument initialized with the resulting temporary. That's why the current (2.1/E&S) definition only allows such an initialization if the reference is const (i.e., const X&) and the target consequently cannot be modified. -- William M. Miller, Glockenspiel, Ltd. wmm@world.std.com