By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,193 Members | 843 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,193 IT Pros & Developers. It's quick & easy.

member to pointer conversions - mommy look what I found

P: n/a

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 ?

Jul 22 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:br********@dispatch.concentric.net
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)

Jul 22 '05 #2

P: n/a
John Carson wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:br********@dispatch.concentric.net
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.


Jul 22 '05 #3

P: n/a
On 17 Dec 2003 02:28:53 EST, Gianni Mariani <gi*******@mariani.ws>
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
Jul 22 '05 #4

P: n/a
Gianni Mariani <gi*******@mariani.ws> wrote in message news:<br********@dispatch.concentric.net>...
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
Jul 22 '05 #5

P: n/a
Dan Cernat wrote:
Gianni Mariani <gi*******@mariani.ws> wrote in message news:<br********@dispatch.concentric.net>...
....
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::p;
}

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.

Jul 22 '05 #6

P: n/a
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:br********@dispatch.concentric.net
John Carson wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:br********@dispatch.concentric.net

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)

Jul 22 '05 #7

P: n/a
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.

Jul 22 '05 #8

P: n/a
tom_usenet wrote:
On 17 Dec 2003 02:28:53 EST, Gianni Mariani <gi*******@mariani.ws>
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::p;
}

private:

int p;
};

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

Jul 22 '05 #9

P: n/a
On 17 Dec 2003 14:07:50 EST, Gianni Mariani <gi*******@mariani.ws>
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
Jul 22 '05 #10

P: n/a
Gianni Mariani <gi*******@mariani.ws> wrote in message news:<br********@dispatch.concentric.net>...
Dan Cernat wrote:
Gianni Mariani <gi*******@mariani.ws> wrote in message news:<br********@dispatch.concentric.net>...

...
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::p;
}

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.

You shouldn't have gone that distance for that.

class A
{
int a;

public:
A(int n = 0) : a(n)
{}

int* get_a()
{
return &a;
}
};
int main()
{
A myA(10); // a == 10 now
int* p_a = myA.get_a(); // pointer to the private A::a
*p_a = 20; // changes the private A::a

return 0;
}
Yes, I agree with Tom, too.
Jul 22 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.