Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > member to pointer conversions - mommy look what I found

Reply
Thread Tools

member to pointer conversions - mommy look what I found

 
 
Gianni Mariani
Guest
Posts: n/a
 
      12-17-2003

While digging for a work around for a VC++7.1 compiler bug I came to
find an interesting thing about pointer to member conversions.


struct A
{
int a;
};

struct B : A
{
int b;
};

typedef int A::* A_mptr;
typedef int B::* B_mptr;


B_mptr bptr1 = &B::a; // ok no probs

A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this

int main()
{
bptr1 = aptr1; // works - a way to get to private members eh?
aptr1 = bptr1; // error - as expected
}

I would have expected that line *** would have created an error but I
can see that in this case the compiler's behaviour is more interesting.

So there is somthing magic about (&B::a) that am object of type B_mptr
just does not have ?



 
Reply With Quote
 
 
 
 
John Carson
Guest
Posts: n/a
 
      12-17-2003
"Gianni Mariani" <(E-Mail Removed)> wrote in message
news:brp0jl$(E-Mail Removed)
> While digging for a work around for a VC++7.1 compiler bug I came to
> find an interesting thing about pointer to member conversions.
>
>
> struct A
> {
> int a;
> };
>
> struct B : A
> {
> int b;
> };
>
> typedef int A::* A_mptr;
> typedef int B::* B_mptr;
>
>
> B_mptr bptr1 = &B::a; // ok no probs
>
> A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
> A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this
>
> int main()
> {
> bptr1 = aptr1; // works - a way to get to private members eh?
> aptr1 = bptr1; // error - as expected
> }
>
> I would have expected that line *** would have created an error but I
> can see that in this case the compiler's behaviour is more
> interesting.
>
> So there is somthing magic about (&B::a) that am object of type B_mptr
> just does not have ?


Huh? Quoting from yourself:

B_mptr bptr1 = &B::a; // ok no probs

As for line ***, isn't this just a matter of "B is a A", i.e., B can be
used in any context that A can (but the reverse is not true)?


--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

 
Reply With Quote
 
 
 
 
Gianni Mariani
Guest
Posts: n/a
 
      12-17-2003
John Carson wrote:
> "Gianni Mariani" <(E-Mail Removed)> wrote in message
> news:brp0jl$(E-Mail Removed)
>
>>While digging for a work around for a VC++7.1 compiler bug I came to
>>find an interesting thing about pointer to member conversions.
>>
>>
>>struct A
>>{
>> int a;
>>};
>>
>>struct B : A
>>{
>> int b;
>>};
>>
>>typedef int A::* A_mptr;
>>typedef int B::* B_mptr;
>>
>>
>>B_mptr bptr1 = &B::a; // ok no probs
>>
>>A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
>>A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this
>>
>>int main()
>>{
>> bptr1 = aptr1; // works - a way to get to private members eh?
>> aptr1 = bptr1; // error - as expected
>>}
>>
>>I would have expected that line *** would have created an error but I
>>can see that in this case the compiler's behaviour is more
>>interesting.
>>
>>So there is somthing magic about (&B::a) that am object of type B_mptr
>>just does not have ?

>
>
> Huh? Quoting from yourself:
>
> B_mptr bptr1 = &B::a; // ok no probs


What's the "huh" for ? data member a is visible in b.

What's even more interesting is that you can to an implicit downcast:

B_mptr bptr2 = &A::a;

>
> As for line ***, isn't this just a matter of "B is a A", i.e., B can be
> used in any context that A can (but the reverse is not true)?


exactly.

So this below does an implicit upcast from class B to class A and note
that when trying to do this with member b it fails.

A_mptr aptr1 = &B::a;

I'm simply pointing out that this pointer to member stuff seems to have
been well thought through ( at least in a primary way ). How this
interacts with complex constructs needs a little more study on my part.








 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      12-17-2003
On 17 Dec 2003 02:28:53 EST, Gianni Mariani <(E-Mail Removed)>
wrote:

>
>While digging for a work around for a VC++7.1 compiler bug I came to
>find an interesting thing about pointer to member conversions.
>
>
>struct A
>{
> int a;
>};
>
>struct B : A
>{
> int b;
>};
>
>typedef int A::* A_mptr;
>typedef int B::* B_mptr;
>
>
>B_mptr bptr1 = &B::a; // ok no probs
>
>A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***


No, B::a *is* A::a - no conversion is involved.

>A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this


Right, b was declared in B (and therefore the member pointer has type
int B::*), and there was no conversion from int B::* to int A::*.

>
>int main()
>{
> bptr1 = aptr1; // works - a way to get to private members eh?


You can convert T A::* to T B::* since B has all of A's members. The
same applies to member function pointers. But you can only access
&A::i where you can access A::i (e.g. inside A and its friends), so
there's no problem.

> aptr1 = bptr1; // error - as expected
>}
>
>I would have expected that line *** would have created an error but I
>can see that in this case the compiler's behaviour is more interesting.


There's no reason to forbid something harmless that might be useful.

>So there is somthing magic about (&B::a) that am object of type B_mptr
>just does not have ?


Yes, the type of &B::a is not "int B::*" - it is "int A::*".
Name-lookup on B::a finds A::a, and the type of &A::a is "int A::*".

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
Reply With Quote
 
Dan Cernat
Guest
Posts: n/a
 
      12-17-2003
Gianni Mariani <(E-Mail Removed)> wrote in message news:<brp0jl$(E-Mail Removed)>...
> While digging for a work around for a VC++7.1 compiler bug I came to
> find an interesting thing about pointer to member conversions.
>
>
> struct A
> {
> int a;
> };
>
> struct B : A
> {
> int b;
> };
>
> typedef int A::* A_mptr;
> typedef int B::* B_mptr;
>
>
> B_mptr bptr1 = &B::a; // ok no probs
>
> A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
> A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this
>
> int main()
> {
> bptr1 = aptr1; // works - a way to get to private members eh?

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
nope, you used structs. if you use classes, the members are private
and this line will not compile

> aptr1 = bptr1; // error - as expected
> }
>
> I would have expected that line *** would have created an error but I
> can see that in this case the compiler's behaviour is more interesting.
>
> So there is somthing magic about (&B::a) that am object of type B_mptr
> just does not have ?


I wouldn't bet my money on it, but it has to be because B is derived
from A.

/dan
 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      12-17-2003
Dan Cernat wrote:
> Gianni Mariani <(E-Mail Removed)> wrote in message news:<brp0jl$(E-Mail Removed)>...
>

....
>>int main()
>>{
>> bptr1 = aptr1; // works - a way to get to private members eh?

>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
> nope, you used structs. if you use classes, the members are private
> and this line will not compile


That's not what I meant ... here is the example where access to private
members can be violated.

struct A
{
int a;

// allow access to private p
static int A::* make_a_ptr()
{
return &A:;
}

private:

int p;
};

struct B : A
{
int b;
};


typedef int A::* A_mptr;
typedef int B::* B_mptr;



A_mptr aptr1 = &B::a;
//A_mptr aptr2 = &B::b;

B_mptr bptr1 = &B::a;
B_mptr bptr2 = &A::a;

B_mptr bptr3 = A::make_a_ptr();

// bptr3 accesses a private membe of A

int main()
{
bptr1 = aptr1;
// aptr1 = bptr1;
}



>
>
>> aptr1 = bptr1; // error - as expected
>>}
>>
>>I would have expected that line *** would have created an error but I
>>can see that in this case the compiler's behaviour is more interesting.
>>
>>So there is somthing magic about (&B::a) that am object of type B_mptr
>>just does not have ?

>
>
> I wouldn't bet my money on it, but it has to be because B is derived
> from A.


Tom's post explains that &B::a == &A::a and is an int A::*, not a B::*.

I confirmed that.

 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      12-17-2003
"Gianni Mariani" <(E-Mail Removed)> wrote in message
news:brpan2$(E-Mail Removed)
> John Carson wrote:
> > "Gianni Mariani" <(E-Mail Removed)> wrote in message
> > news:brp0jl$(E-Mail Removed)
> >
> > >
> > > So there is somthing magic about (&B::a) that am object of type
> > > B_mptr just does not have ?

> >
> >
> > Huh? Quoting from yourself:
> >
> > B_mptr bptr1 = &B::a; // ok no probs

>
> What's the "huh" for ? data member a is visible in b.


My "huh" referred to your statement.

"So there is somthing magic about (&B::a) that am object of type B_mptr just
does not have?"

You assign &B::a to an object of type B_mptr when you do:

B_mptr bptr1 = &B::a; // ok no probs

so it was not clear to me why you should be emphasising the differences
between the type on the left hand side and the type on the right hand side.

I am guessing now that you were referring to the contrast between the
two lines:

A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this

i.e., &B::a and &B::b (which is of type B_mptr) behave differently.

> I'm simply pointing out that this pointer to member stuff seems to
> have been well thought through ( at least in a primary way ).


Yes, it seems to work nicely.

--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      12-17-2003
John Carson wrote:
....
>
> I am guessing now that you were referring to the contrast between the
> two lines:


yep.

>
> A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
> A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this
>
> i.e., &B::a and &B::b (which is of type B_mptr) behave differently.
>


<Knit pick alert>

So Tom points out (and it seems confirmed on gcc at least) that &B::a is
NOT of type int B::* but in fact of type int A::* .

In general, the type of &T::a is *really* Y Z::* where Z is the type of
the class that contains the member 'a', and Y obviously is the type of
the member.

This is the magic.

 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      12-17-2003
tom_usenet wrote:
> On 17 Dec 2003 02:28:53 EST, Gianni Mariani <(E-Mail Removed)>
> wrote:
>

....
> You can convert T A::* to T B::* since B has all of A's members. The
> same applies to member function pointers. But you can only access
> &A::i where you can access A::i (e.g. inside A and its friends), so
> there's no problem.


I wasn't suggesting a "problem" per se. I was just suggesting that you
could. (and I have no idea WHY you would want to this)

example:

struct A
{
int a;

// allow access to private p
static int A::* make_a_ptr()
{
return &A:;
}

private:

int p;
};

....
ap->*(A::make_a_ptr()) = 2;
....

 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      12-18-2003
On 17 Dec 2003 14:07:50 EST, Gianni Mariani <(E-Mail Removed)>
wrote:

>John Carson wrote:
>...
>>
>> I am guessing now that you were referring to the contrast between the
>> two lines:

>
>yep.
>
>>
>> A_mptr aptr1 = &B::a; // hmm converts B::a to A::a ***
>> A_mptr aptr2 = &B::b; // error - spooky - knows it can't do this
>>
>> i.e., &B::a and &B::b (which is of type B_mptr) behave differently.
>>

>
><Knit pick alert>
>
>So Tom points out (and it seems confirmed on gcc at least) that &B::a is
>NOT of type int B::* but in fact of type int A::* .
>
>In general, the type of &T::a is *really* Y Z::* where Z is the type of
>the class that contains the member 'a', and Y obviously is the type of
>the member.
>
>This is the magic.


It's a natural consequence of name lookup. "T::a" doesn't denote the
member "a" of T, but a name "a" that can be found in the scope of T or
its base classes (of course, names that can be found in the scope of T
or its base classes are members!). Here's an odd example (that some
popular compilers get wrong)

int i;

struct A
{
static int i;
};

struct B
{
static int i;
};

struct C: A, B
{
using B::i;
};

int main()
{
int* p = &C::i;
}

C::i causes name lookup for i in C. There are two i's, however the
using declaration means that B::i is found in the scope of C before
checking A or B.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointer to integer to pointer conversions lithiumcat@gmail.com C Programming 11 05-08-2008 12:52 PM
My mommy is in the hospital :( High_Heel_Lover Computer Support 0 10-21-2007 04:09 PM
Pointer to pointer to const conversions James Aguilar C++ 3 06-22-2006 09:00 AM
Pointer conversions and Data types conversions vb@gmail.com C Programming 10 08-05-2005 09:51 AM
Consultant FU*KS his mommy ! Rowdy Yates MCSE 7 09-10-2004 01:44 AM



Advertisments