473,386 Members | 2,129 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Casting pointer to derived class and vice versa

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
9 3444
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
"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
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
"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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Vinodh Kumar | last post by:
I see that casting changes the value of a pointer in case of multiple inheritance.In single inheritance also it is the same know?Isn't it? Vinodh Kumar P
4
by: Bren | last post by:
Hi all, Given this situation: class Base { typedef void (Base::*FN_FOO)(); virtual void Foo() = 0; // pure virtual void GetFoo(FN_FOO pfnFoo) = 0; // pure virtual
13
by: JustSomeGuy | last post by:
I have two object types ClassA and ClassB class ClassA { public: int data; operator ClassB() { ClassB b; b.data = data + 1; return (b);
7
by: JustSomeGuy | last post by:
I have two classes, class english and class metric. I seem to be having dificulty getting this to compile properly... I'm using powerpc-apple-darwin8-g++-4.0.0 There are 5 files, main.cpp...
23
by: René Nordby | last post by:
Hi there, Is there anyone that knows how to do the following? I have a class A and a class B, that 100% inherits from class A (this means that I don't have other code in class B, than...
8
by: David Williams | last post by:
Hi all, I have a templated Vector3D class which holds (x,y,z) components as the specified type. I quite often wish to cast a Vector3D holding ints into a Vector3D holding floats and vice versa....
9
by: Jess | last post by:
Hello, It seems both static_cast and dynamic_cast can cast a base class pointer/reference to a derived class pointer/reference. If so, is there any difference between them? In addition, if I...
7
by: WaterWalk | last post by:
Hello. I thought I understood member function pointers, but in fact I don't. Consider the following example: class Base { public: virtual ~Base() {} }; class Derived : public Base {
32
by: alex.j.k2 | last post by:
Hello all, I have "PRECISION" defined in the preprocessor code and it could be int, float or double, but I do not know in the code what it is. Now if I want to assign zero to a "PRECISION"...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.