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

Casting pointer to derived class and vice versa

P: n/a
Hi everyone,

I was experimenting with static_cast and reinterpret cast

#include <iostream>

struct A1 { int a; };
struct A2 { double d; };

struct B : public A1, A2
{
int v;
};

int main()
{
// one B object
B b;

// two A2 pointers
A2 * p1;
A2 * p2;

// set both pointers to &b

p1 = static_cast<A2*>(&b);
p2 = reinterpret_cast<A2*>(&b);

// same type, same B object...
// but point to different addresses:
std::cout << "p1: " << p1 << "\n";
std::cout << "p2: " << p2 << "\n";

// the pointers are not equal
assert (p1 == p2); // fails
}

Program Output:

p1: 0xbffff97c
p2: 0xbffff978
Assertion failed: (p1 == p2), function main, file test.cc, line
30.
Abort trap

AFAICT, the difference between the two casts is that static_cast knows
that you're casting down, so it adjusts the value of the pointer
accordingly. reinterpret_cast is just a brute cast.

Previous to this, I thought that different pointer types to the same
underlying object would still store the same address, but the
differing pointer types was more of an indication to the compiler what
expressions the pointer could support. It seems from this experiment
that this is incorrect. Is the reason why the derived pointer moves up
in memory is because of the memory layout, something like this:
TOP OF STACK
------------ <- pointer to derived class
derived members can also 'see' base class members,
. if we think of visibility
. as extending downwards
------------ <- pointer to base can not 'see' derived
members
base members
------------
BOTTOM OF STACK

Is this even defined in C++, or is it implementation specific?

Interestingly when you assign a derived pointer to a base pointer, the
value stored doesn't change, even with a static_cast. This is more
inline with how I thought pointers would originally behave.

So casting from a base to a derived will change the value stored by
the pointer, but casting (or assigning) from a derived to a base will
not change the value. Is there a reason for this?

Thanks

Taras
Jun 27 '08 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Taras_96 wrote:
Is the reason why the derived pointer moves up
in memory is because of the memory layout, something like this:
TOP OF STACK
------------ <- pointer to derived class
derived members can also 'see' base class members,
. if we think of visibility
. as extending downwards
------------ <- pointer to base can not 'see' derived
members
base members
------------
BOTTOM OF STACK

Is this even defined in C++, or is it implementation specific?
It's implementation specific. You can pretty much be sure that
something 'like' this is happening though.
Jun 27 '08 #2

P: n/a
"Taras_96" <ta******@gmail.comwrote in message Hi everyone,
>
I was experimenting with static_cast and reinterpret cast

#include <iostream>

struct A1 { int a; };
struct A2 { double d; };

struct B : public A1, A2
{
int v;
};

int main()
{
// one B object
B b;

// two A2 pointers
A2 * p1;
A2 * p2;

// set both pointers to &b

p1 = static_cast<A2*>(&b);
p2 = reinterpret_cast<A2*>(&b);

// same type, same B object...
// but point to different addresses:
std::cout << "p1: " << p1 << "\n";
std::cout << "p2: " << p2 << "\n";

// the pointers are not equal
assert (p1 == p2); // fails
}

Program Output:

p1: 0xbffff97c
p2: 0xbffff978
Assertion failed: (p1 == p2), function main, file test.cc, line
30.
Abort trap

AFAICT, the difference between the two casts is that static_cast knows
that you're casting down, so it adjusts the value of the pointer
Where are you casting down?
accordingly. reinterpret_cast is just a brute cast.
static_cast would make the derived class pointer point to the appropriate
base class (as laid out in memory), hence you see different values.
reinterpret_cast is just a reinterpretation of the bits. Of course this is
implementation defined. You could check "Inside the C++ Object Model" book
by Lippman for more details.

[snip]
Is this even defined in C++, or is it implementation specific?
Implementation defined.
Interestingly when you assign a derived pointer to a base pointer, the
value stored doesn't change, even with a static_cast. This is more
inline with how I thought pointers would originally behave.
What? Is this in line with what you saw in your sample program?
So casting from a base to a derived will change the value stored by
the pointer, but casting (or assigning) from a derived to a base will
not change the value. Is there a reason for this?
Check dynamic_cast for downcasting.

--
http://techytalk.googlepages.com
Jun 27 '08 #3

P: n/a
sk_usenet wrote:
"Taras_96" <ta******@gmail.comwrote in message Hi everyone,
>>
I was experimenting with static_cast and reinterpret cast

#include <iostream>

struct A1 { int a; };
struct A2 { double d; };

struct B : public A1, A2
{
int v;
};

int main()
{
// one B object
B b;

// two A2 pointers
A2 * p1;
A2 * p2;

// set both pointers to &b

p1 = static_cast<A2*>(&b);
p2 = reinterpret_cast<A2*>(&b);

// same type, same B object...
// but point to different addresses:
std::cout << "p1: " << p1 << "\n";
std::cout << "p2: " << p2 << "\n";

// the pointers are not equal
assert (p1 == p2); // fails
}

Program Output:

p1: 0xbffff97c
p2: 0xbffff978
Assertion failed: (p1 == p2), function main, file test.cc, line
30.
Abort trap

AFAICT, the difference between the two casts is that static_cast
knows that you're casting down, so it adjusts the value of the
pointer

Where are you casting down?
The meaning of "Down" and "Up" is open for debate. Some consider
the root of the tree to be at the top. I've never seen a real tree
like that. Heard of it, but never seen one.
>accordingly. reinterpret_cast is just a brute cast.

static_cast would make the derived class pointer point to the
appropriate base class (as laid out in memory), hence you see
different values.
"Hence"? There is no 'static_cast' required to convert from the
derived class to the accessible unambiguous base class. And the
different values are only because the sizes of the base class
subobjects are not 0, so they occupy some space in the derived
class object. Using 'reinterpret_cast' in this situation is
simply not legal.
reinterpret_cast is just a reinterpretation of the
bits. Of course this is implementation defined. You could check
"Inside the C++ Object Model" book by Lippman for more details.

[snip]
>Is this even defined in C++, or is it implementation specific?
Implementation defined.
>Interestingly when you assign a derived pointer to a base pointer,
the value stored doesn't change, even with a static_cast. This is
more inline with how I thought pointers would originally behave.

What? Is this in line with what you saw in your sample program?
>So casting from a base to a derived will change the value stored by
the pointer, but casting (or assigning) from a derived to a base will
not change the value. Is there a reason for this?

Check dynamic_cast for downcasting.
Again, you seem to use different meaning of "down-" or "up-" AFA
casting is concerned. And 'dynamic_cast' is NOT going to work
here because the classes are not polymorphic. And, BTW, even for
what you call "downcasting", static_cast is perfectly OK:

B b;
A1 *pa1 = &b;
A2 *pa2 = &b;

B *pb1 = static_cast<B*>(pa1);
B *pb2 = static_cast<B*>(pa2);

assert(pb1 == pb2);

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #4

P: n/a
"Victor Bazarov" <v.********@comAcast.netwrote in message
sk_usenet wrote:
>"Taras_96" <ta******@gmail.comwrote in message Hi everyone,
[snip]
>>AFAICT, the difference between the two casts is that static_cast
knows that you're casting down, so it adjusts the value of the
pointer

Where are you casting down?

The meaning of "Down" and "Up" is open for debate. Some consider
the root of the tree to be at the top. I've never seen a real tree
like that. Heard of it, but never seen one.
What is your _interpretation_ of downcasting?
>>accordingly. reinterpret_cast is just a brute cast.

static_cast would make the derived class pointer point to the
appropriate base class (as laid out in memory), hence you see
different values.

"Hence"? There is no 'static_cast' required to convert from the
Did I imply that a static_cast was essentially required? If so, then thanks
for clarifying it.

[snip]
>>So casting from a base to a derived will change the value stored by
the pointer, but casting (or assigning) from a derived to a base will
not change the value. Is there a reason for this?

Check dynamic_cast for downcasting.

Again, you seem to use different meaning of "down-" or "up-" AFA
casting is concerned. And 'dynamic_cast' is NOT going to work
True, I overlooked that part. But the intention was to look beyond
static_cast and reinterpret_cast
for so-called "downcasting".
here because the classes are not polymorphic. And, BTW, even for
what you call "downcasting", static_cast is perfectly OK:
--
http://techytalk.googlepages.com
Jun 27 '08 #5

P: n/a
On Apr 25, 12:42 am, "sk_usenet" <sometechyguy at gmail dot com>
wrote:
"Taras_96" <taras...@gmail.comwrote in message Hi everyone,

Interestingly when you assign a derived pointer to a base pointer, the
value stored doesn't change, even with a static_cast. This is more
inline with how I thought pointers would originally behave.

What? Is this in line with what you saw in your sample program?
That a pointer to an object, regardless of whether the pointer is a
pointer to a base type or a derived type, will always point to the
same place.
Jun 27 '08 #6

P: n/a
On Apr 25, 1:27 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
sk_usenet wrote:
"Taras_96" <taras...@gmail.comwrote in message Hi everyone,

static_cast would make the derived class pointer point to the
appropriate base class (as laid out in memory), hence you see
different values.

"Hence"? There is no 'static_cast' required to convert from the
derived class to the accessible unambiguous base class. And the
different values are only because the sizes of the base class
subobjects are not 0, so they occupy some space in the derived
class object. Using 'reinterpret_cast' in this situation is
simply not legal.

Could you explain the 'subojbects' bit a bit further? I think that's
the answer to my question. (in the code below, both Derived and Base
have one int member each)

Derived* pDerived = new Derived(); // pDerived points to a Derived
object
Base* pBase = static_cast<Base*>(pDerived); // address hasn't
changed
Derived* pDerived3 = static_cast<Derived*>(pBase); // address hasn't
changed

I found that casting to a base class (even though, AFAIK, the
static_cast isn't required), doesn't change the address, and neither
does casting back up to the Derived class.

Base* pBaseNext = new Derived();
Derived* pDerivedNext = static_cast<Derived*>(pBaseNext);

Both of these values are also the same.

So how come in my first example the values were changing?

Thanks

Taras
Jun 27 '08 #7

P: n/a
On Apr 24, 7:27 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
sk_usenet wrote:
"Taras_96" <taras...@gmail.comwrote in message Hi everyone,
accordingly. reinterpret_cast is just a brute cast.
static_cast would make the derived class pointer point to the
appropriate base class (as laid out in memory), hence you see
different values.
"Hence"? There is no 'static_cast' required to convert from the
derived class to the accessible unambiguous base class. And the
different values are only because the sizes of the base class
subobjects are not 0, so they occupy some space in the derived
class object.
Just a nit but, while your statement is generally true in
practice, the standard doesn't require it. The standard gives
the compiler pretty much unlimited leeway in how it lays things
out when inheritance is involved, and even in the simplest
cases, there's no guarantee that the address of the base class
is the same as the address of the derived class.
Using 'reinterpret_cast' in this situation is simply not
legal.
The reinterpret_cast itself is legal. Doing anything with the
results of it isn't (except for casting it back to the original
type).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #8

P: n/a
On Apr 24, 8:43*am, Taras_96 <taras...@gmail.comwrote:
Hi everyone,

I was experimenting with static_cast and reinterpret cast

* * *#include <iostream>

* * *struct A1 { int a; };
* * *struct A2 { double d; };

* * *struct B : public A1, A2
* * *{
* * * * *int v;
* * *};

* * *int main()
* * *{
* * * * *// one B object
* * * * *B b;

* * * * *// two A2 pointers
* * * * *A2 * p1;
* * * * *A2 * p2;

* * * * *// set both pointers to &b

* * * * *p1 = static_cast<A2*>(&b);
* * * * *p2 = reinterpret_cast<A2*>(&b);

* * * * *// same type, same B object...
* * * * *// but point to different addresses:
* * * * *std::cout << "p1: " << p1 << "\n";
* * * * *std::cout << "p2: " << p2 << "\n";

* * * * *// the pointers are not equal
* * * * *assert (p1 == p2); // fails
* * *}

* * *Program Output:

* * *p1: 0xbffff97c
* * *p2: 0xbffff978
* * *Assertion failed: (p1 == p2), function main, file test.cc, line
30.
* * *Abort trap
I'm sure that you did not intend to create the impression that you
wrote the above program in the course of your "experimenting" with
various C++ cast operators.

But without properly attributing the origin of the program include in
your post:

http://preview.tinyurl.com/57k6td

readers might well be left with that impression that this (superbly
written - I might add :-)) C++ program was yours. I believe that
properly citing one's sources is always the right thing to do - even
in a USENET post.

Greg

Jun 27 '08 #9

P: n/a
On Apr 26, 2:19 am, Greg Herlihy <gre...@mac.comwrote:
On Apr 24, 8:43 am, Taras_96 <taras...@gmail.comwrote:
Hi everyone,
I was experimenting with static_cast and reinterpret cast
#include <iostream>
struct A1 { int a; };
struct A2 { double d; };
struct B : public A1, A2
{
int v;
};
int main()
{
// one B object
B b;
// two A2 pointers
A2 * p1;
A2 * p2;
// set both pointers to &b
p1 = static_cast<A2*>(&b);
p2 = reinterpret_cast<A2*>(&b);
// same type, same B object...
// but point to different addresses:
std::cout << "p1: " << p1 << "\n";
std::cout << "p2: " << p2 << "\n";
// the pointers are not equal
assert (p1 == p2); // fails
}
Program Output:
p1: 0xbffff97c
p2: 0xbffff978
Assertion failed: (p1 == p2), function main, file test.cc, line
30.
Abort trap

I'm sure that you did not intend to create the impression that you
wrote the above program in the course of your "experimenting" with
various C++ cast operators.

But without properly attributing the origin of the program include in
your post:

http://preview.tinyurl.com/57k6td

readers might well be left with that impression that this (superbly
written - I might add :-)) C++ program was yours. I believe that
properly citing one's sources is always the right thing to do - even
in a USENET post.

Greg
Ok, sorry Greg - will cite all source from now :).

Jun 27 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.