C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

References to Pointers And Polymorphism

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Brian Neal
Guest





PostPosted: Fri Jan 23, 2004 10:03 am    Post subject: References to Pointers And Polymorphism Reply with quote



Please consider the following code:

class B {};
class D : public B {};

D d;
D* dPtr = &d;
B* bPtr = dPtr; // fine
B& bRef = d; // fine

D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef; // ********* oops ************

bPtrRef = dPtr; // fine

The line marked "oops" generates warnings on 2 compilers I use, saying
a temporary will be used in order to initialize bPtrRef.

For some reason I cannot wrap my mind around this. I was just going to
add a cast, but the temporary warning makes me think it will not do
what I want anyway. Can someone explain what is happening here?
Thanks.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Francis Glassborow
Guest





PostPosted: Fri Jan 23, 2004 9:03 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote



In message <26d6ee84.0401220539.299bcc30 (AT) posting (DOT) google.com>, Brian Neal
<SurfCedarRapids (AT) netscape (DOT) net> writes
Quote:
Please consider the following code:

class B {};
class D : public B {};

So all Ds are also Bs. That means that all pointers/references to B may
also point/reference Ds. However it does not mean that all pointers to D
are pointers to B. I.e. the relationship is between B and D NOT between
B* and D*. This is something that is subtle but essential to understand.
It begins to bite unpleasantly when you have a multiple inheritance
hierarchy. The Compiler has no way to know that you do not somewhere
else provide such a relationship: e.g.:

class C : public D, public B {};

Now a B* might be pointing to either of two B sub-objects, whether it is
a subobject of D depends on how you initialise it.

Quote:

D d;
D* dPtr = &d;
B* bPtr = dPtr; // fine
B& bRef = d; // fine

D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef;

And here you treat a D* as if it is a B* but it isn't (it is the wrong
type) so the compiler has two options, it can outright reject your code
or it can (incorrectly IMO) be try to be 'helpful' and create a
temporary instance of a B* to bind to the reference. Incorrectly because
the licence to bind references to temporaries is only allowed for const
references.

Quote:
// ********* oops ************

bPtrRef = dPtr; // fine

The line marked "oops" generates warnings on 2 compilers I use, saying
a temporary will be used in order to initialize bPtrRef.

For some reason I cannot wrap my mind around this. I was just going to
add a cast, but the temporary warning makes me think it will not do
what I want anyway. Can someone explain what is happening here?
Thanks.

The question is, of course, exactly what it is that you want because the
compiler is correct in posting 'here be dragons' notices on your code.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Fri Jan 23, 2004 9:06 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote



Brian Neal wrote:
Quote:
class B {};
class D : public B {};

D d;
D* dPtr = &d;
D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef; // ********* oops ************

The line marked "oops" generates warnings on 2 compilers I use, saying
a temporary will be used in order to initialize bPtrRef.

A pointer to D doesn't have an ISA relationship with a pointer to B. When
converting from D* to B*, which is possible, a temporary is created.

BTW, take a look at this:
D* pd;
B*& pb = pb;
pb = new B;// oops, pd now points to a B!

Uli


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Fri Jan 23, 2004 9:11 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote

Brian Neal wrote:
Quote:
Please consider the following code:

class B {};
class D : public B {};

D d;
D* dPtr = &d;
B* bPtr = dPtr; // fine
B& bRef = d; // fine

D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef; // ********* oops ************

bPtrRef = dPtr; // fine

The line marked "oops" generates warnings on 2 compilers I use, saying
a temporary will be used in order to initialize bPtrRef.

These compilers are broken; they should not allow the conversion at
all.

Quote:
For some reason I cannot wrap my mind around this. I was just going to
add a cast, but the temporary warning makes me think it will not do
what I want anyway. Can someone explain what is happening here?

Suppose this kind of conversion was allowed on references. Then you
could do:

B*& bPtrRef = dPtrRef; // bPtrRef is alias for dPtr
bPtrRef = new B; // dPtr now points to a B
dPtr->some_method_on_D(); // oops!

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Hyman Rosen
Guest





PostPosted: Sat Jan 24, 2004 1:12 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote

Brian Neal wrote:
Quote:
Can someone explain what is happening here?

If your code were legal, then you could assign
an arbitrary B* to bPtrRef, resulting in a D*
variable (dPtr) holding a non-D* pointer.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Eugene Alterman
Guest





PostPosted: Mon Jan 26, 2004 12:05 am    Post subject: Re: References to Pointers And Polymorphism Reply with quote

"Brian Neal" <SurfCedarRapids (AT) netscape (DOT) net> wrote

Quote:
Please consider the following code:

class B {};
class D : public B {};

D d;
D* dPtr = &d;
B* bPtr = dPtr; // fine
B& bRef = d; // fine

D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef; // ********* oops ************

bPtrRef = dPtr; // fine

The line marked "oops" generates warnings on 2 compilers I use, saying
a temporary will be used in order to initialize bPtrRef.

For some reason I cannot wrap my mind around this. I was just going to
add a cast, but the temporary warning makes me think it will not do
what I want anyway. Can someone explain what is happening here?

A similar thing is happening here:

int i = 5;
long l = i; // fine

int& iRef = i; // fine
long& lRef = iRef // ********* oops ************

lRef = i; // fine

I suppose the above does not baffle you.
An int is convertible to a long, but an int is not a long.

D* is convertible to B* (since a D 'IS A' B), but a D* IS NOT a B*.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Allan W
Guest





PostPosted: Wed Jan 28, 2004 1:29 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote

Quote:
Brian Neal <SurfCedarRapids (AT) netscape (DOT) net> writes
D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef;

Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
Quote:
here you treat a D* as if it is a B* but it isn't (it is the wrong
type)

agreed

Quote:
so the compiler has two options, it can outright reject your code
or it can (incorrectly IMO) be try to be 'helpful' and create a
temporary instance of a B* to bind to the reference.

It really need to allow this code to be compiled -- for legacy support
(pre-standard C++). I doubt there's much code left that needs it, though.
The C++ standard mandates a 'diagnostic message' but it doesn't say that
this can't just be a warning.

Note: When you get a warning, it normally means you have made a mistake!
Just because your code compiles doesn't mean it doesn't have mistakes.

Quote:
Incorrectly because
the licence to bind references to temporaries is only allowed for const
references.

I don't have D&C in front of me, but I think I understand this reasoning.
If you're using a const reference, you probably only want to read the
values. Even if you don't realize that you have a temporary, it was
constructed by copying values from the original object, so this will
work mostly correctly. (I think I could construct counter-examples based
on executing methods of the base class instead of the derived class, but
in the absence of this type of problem it ought to get the correct
values the vast majority of the time.)

OTOH, if you use a non-const reference, you might very well want to
make changes to the object. Now it matters that you're modifying a
temporary instead of the original object -- if you don't realize
you're using a temporary, your changes will be lost.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Wed Jan 28, 2004 8:12 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote

In message <7f2735a5.0401271248.1193f57a (AT) posting (DOT) google.com>, Allan W
<allan_w (AT) my-dejanews (DOT) com> writes
Quote:
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
here you treat a D* as if it is a B* but it isn't (it is the wrong
type)

agreed

so the compiler has two options, it can outright reject your code
or it can (incorrectly IMO) be try to be 'helpful' and create a
temporary instance of a B* to bind to the reference.

It really need to allow this code to be compiled -- for legacy support
(pre-standard C++). I doubt there's much code left that needs it, though.
The C++ standard mandates a 'diagnostic message' but it doesn't say that
this can't just be a warning.

Yes, you are right. In general once a compiler has issued at least one
diagnostic message a TU it can go ahead and do anything. In this case I
would be happy with the quality of the implementation if it always
warned (at all warning levels) about creating a temporary as an
'extension'.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Balog Pal
Guest





PostPosted: Wed Jan 28, 2004 8:34 pm    Post subject: Re: References to Pointers And Polymorphism Reply with quote

"Allan W" <allan_w (AT) my-dejanews (DOT) com> wrote


Quote:
D*& dPtrRef = dPtr; // fine
B*& bPtrRef = dPtrRef;

so the compiler has two options, it can outright reject your code
or it can (incorrectly IMO) be try to be 'helpful' and create a
temporary instance of a B* to bind to the reference.

If you're using a const reference, you probably only want to read the
values. Even if you don't realize that you have a temporary, it was
constructed by copying values from the original object, so this will
work mostly correctly. (I think I could construct counter-examples based
on executing methods of the base class instead of the derived class, but
in the absence of this type of problem it ought to get the correct
values the vast majority of the time.)

In the example we have a pointer. So what you write can not apply. As a
pointer is a builtin type. And if you go dereferencing it, any polymorphic
bahavior will work fine. And nonpolymorphic behavior will work 'as
requested' ;)

B* const & bPtrRef = dPtrRef;

could compile binding making bPtrRef bound to a copy of dPtr created in a
temporary. The already mentioned problem of setting the pointer to point to
something else can't strike due to constness. Though if the programmer is
not aware of the copy, he van do

delete dPtr; dPtr = new ... ;

leaving bPtrRef dongling.

Quote:
OTOH, if you use a non-const reference, you might very well want to
make changes to the object. Now it matters that you're modifying a
temporary instead of the original object -- if you don't realize
you're using a temporary, your changes will be lost.

That is the other side of the problem.

Paul



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.