static_cast vs reinterpert_cast

R

Rahul

Hi,

I have a
class A : public B {...member functions......data members};

and am doing the following
A *p=new A();
void *p=static_cast<void *>(p);
factory_instance->process(p);

Here p is passed to a function, which accepts void ptr. That function
need to cast it back
A *pp=static_cast<A *>(p);

The function is in the factory which accepts void *p only, the specific
implementations need to cast the pointer back to the expected class
and use it.

Question:Though both works fine, yet I want to know what is more
appropriate in this situation static_cast OR reinterpert_cast

The books suggests
static_cast=> "For "well-behaved" and "reasonably
well-behaved" casts,including things you might now do without a cast
reinterpret_cast=> To cast to a completely different meaning. The key
is that you'll need to cast back to the original type to use it
safely.

But I am not able to interpret the sentences in this context :)
 
T

tragomaskhalos

Rahul said:
and am doing the following
A *p=new A();
void *p=static_cast<void *>(p);
factory_instance->process(p);

Here p is passed to a function, which accepts void ptr. That function
need to cast it back
A *pp=static_cast<A *>(p);

Don't cast to void* before calling process(), it's not needed and the
less casts you have the better - just pass the A* as is like this:
A* pa = new A();
factory_instance->process(pa);
Casting back to A* inside process() should be fine.
It'd obviously be better if process() took an A* (or some Base-of-A*)
in the first place.
 
R

Rolf Magnus

Rahul said:
Hi,

I have a
class A : public B {...member functions......data members};

and am doing the following
A *p=new A();
void *p=static_cast<void *>(p);
factory_instance->process(p);

Here p is passed to a function, which accepts void ptr.

No need for a static_cast. You can convert a pointer to an object into a
pointer to void implicitly.
That function
need to cast it back
A *pp=static_cast<A *>(p);

The function is in the factory which accepts void *p only, the specific
implementations need to cast the pointer back to the expected class
and use it.

Question:Though both works fine, yet I want to know what is more
appropriate in this situation static_cast OR reinterpert_cast

static_cast. Generally, one could say that you should choose static_cast
over reinterpret_cast if it does the job.
The books suggests
static_cast=> "For "well-behaved" and "reasonably
well-behaved" casts,including things you might now do without a cast
reinterpret_cast=> To cast to a completely different meaning. The key
is that you'll need to cast back to the original type to use it
safely.

But I am not able to interpret the sentences in this context :)

You could translate it to "reinterpret_cast is more evil than
static_cast" ;-)
 
S

sonison.james

Hi,

static_cast is meant to be used for cases which the compiler would
automatically be able to convert, such as char to int and in your case
A* to void*. reinterpret_cast is used, as the book mentions, for
low-level hacks, especially when you know what you are doing, eg:

struct S
{
int a, b;
};

int main()
{
S s;
s.a = 10;
s.b = 20;

int* p = reinterpret_cast<int*>(&s);
cout << "a=" << *p << endl;
++p;
cout << "b=" << *p << endl;
}

Typically reinterpret_cast should work where a static_cast works.
"Ideally" in C++ we should avoid using void* as much because we loose
type safety. Also in your case you do seem to be having a class
hierarchy (A,B), so using virtual functions with base ptrs would be
cleaner (if virtual fn overhead is not an issue).

Thanks and regards
Sonison James
 
R

Ron Natalie

Rahul said:
The books suggests
static_cast=> "For "well-behaved" and "reasonably
well-behaved" casts,including things you might now do without a cast
reinterpret_cast=> To cast to a completely different meaning. The key
is that you'll need to cast back to the original type to use it
safely.
If your books say that, burn them. That's not the definition of
static cast.

There are two meanings for static cast:

1. Forcing conversions that could happen anyway:

static_cast<int>(5.5)

2. With the exception of const conversions, reversing defined conversions:
class B { };
class D : public B { };

B* b = new D; // defined conversion D* ->B*
D* d = static_cast<B*>(b);

It is still incumbent on the application to determine the
validity of the second time type of cast. In this case
making sure that b contains an value that really is
convertable to D*.
 
F

Frederick Gotham

I have a simple rule-of-thumb:

If you can use static_cast, then use static_cast.

If you can't use static_cast, then use reinterpret_cast.
 
V

Victor Bazarov

Frederick said:
I have a simple rule-of-thumb:

If you can use static_cast, then use static_cast.

If you can't use static_cast, then use reinterpret_cast.

I have a simple preceding rule:

If you can do it without a cast, do not use any cast.

V
 
F

Frederick Gotham

Victor Bazarov posted:
I have a simple preceding rule:

If you can do it without a cast, do not use any cast.

Naturally ; )


I tend to use the old-style casts now and again too, e.g.:

enum { len = 64U };

int array[len];

for(size_t i = len - 1; (size_t)-1 != i; --i)


Or if I need a reinterpret_cast and a const_cast at the same time:

char const *pc = 0;

int *pi = (int*)pc;

/* A very contrived example, I realise! */


The major drawback of the new-style casts is that they take up far too much
horizontal screen space.
 
D

dio

Frederick Gotham said:
The major drawback of the new-style casts is that they take up far too much
horizontal screen space.

Yes, which should serve as a visual reminder that a design that relies
heavily on casts is perhaps not ideal.
 
F

Frederick Gotham

dio posted:
Yes, which should serve as a visual reminder that a design that relies
heavily on casts is perhaps not ideal.


I'm out of nappies now though, and I can judge sensibly as to when I should
use what kind of cast. Would you prefer:

int *p = reinterpret_cast<int*>(
const_cast<char*>(pcc)
);

or:

int *p = (char*)pcc;


And,


size_t i = static_cast<size_t>(-1);

or:

size_t i = (size_t)-1;


(Second example is intended to supress a compiler warning)
 
I

Ian Collins

Frederick said:
dio posted:





I'm out of nappies now though, and I can judge sensibly as to when I should
use what kind of cast. Would you prefer:

int *p = reinterpret_cast<int*>(
const_cast<char*>(pcc)
);

or:

int *p = (char*)pcc;
Very much the former. The horrible code emphasises the horrible action!
And,


size_t i = static_cast<size_t>(-1);

or:

size_t i = (size_t)-1;
The former.
 
J

Jim Langston

Frederick Gotham said:
dio posted:



I'm out of nappies now though, and I can judge sensibly as to when I
should
use what kind of cast. Would you prefer:

int *p = reinterpret_cast<int*>(
const_cast<char*>(pcc)
);

This one. It spells out exactly what is going on.
or:

int *p = (char*)pcc;


And,


size_t i = static_cast<size_t>(-1);

This one.
 
R

Rolf Magnus

Frederick said:
Victor Bazarov posted:
I have a simple preceding rule:

If you can do it without a cast, do not use any cast.

Naturally ; )


I tend to use the old-style casts now and again too, e.g.:

enum { len = 64U };

int array[len];

for(size_t i = len - 1; (size_t)-1 != i; --i)

I tend to use constructor-style casts in such a situation:

for(size_t i = len - 1; size_t(-1) != i; --i)

But I think that's just because C style casts look so old-style to me
now ;-)
Or if I need a reinterpret_cast and a const_cast at the same time:

char const *pc = 0;

int *pi = (int*)pc;

/* A very contrived example, I realise! */

That's an example of a situation where I would definitely go with the C++
style casts. One important advantage is that someone reading the code will
immediately see that I really intended to cast away the constness and
didn't just get it in by accident.
 
R

Ron Natalie

Rolf said:
I tend to use constructor-style casts in such a situation:

for(size_t i = len - 1; size_t(-1) != i; --i)

But I think that's just because C style casts look so old-style to me
now ;-)

But a single arg function-style cast is identical in meaning to the
C-style cast. You're back to it possibly meaning static, const,
reinterpret or combinations of the above (as well as busting access
control which there is no C++-style equivelent to).
 
R

Rolf Magnus

Ron said:
But a single arg function-style cast is identical in meaning to the
C-style cast. You're back to it possibly meaning static, const,
reinterpret or combinations of the above (as well as busting access
control which there is no C++-style equivelent to).

I know. As I wrote, it's just that the C style cast looks more C'is than the
constructor style. Also note that none of the things you mentioned are an
issue in the above code example.
 
J

Jim Langston

Ron Natalie said:
But a single arg function-style cast is identical in meaning to the
C-style cast. You're back to it possibly meaning static, const,
reinterpret or combinations of the above (as well as busting access
control which there is no C++-style equivelent to).

Actually, not at all. size_t(-1) tells me exactly what is going on. This
is a size_t variable that is being initialized to -1. There is no ambiguity
at all. It is not techinically a cast, I don't think.
 
R

Richard Herring

Rolf Magnus said:
I tend to use constructor-style casts in such a situation:

for(size_t i = len - 1; size_t(-1) != i; --i)

I'd lose the -1 altogether ;-)

for (size_t i = len; i-- != 0; )
 
R

Rolf Magnus

Jim said:
Actually, not at all. size_t(-1) tells me exactly what is going on. This
is a size_t variable that is being initialized to -1. There is no
ambiguity at all. It is not techinically a cast, I don't think.

size_t is unsigned and can't have negative values. size_t(-1) tells the
compiler that you want -1 converted to size_t, IOW, it's a cast.
 
F

Frederick Gotham

Richard Herring posted:
I'd lose the -1 altogether ;-)

for (size_t i = len; i-- != 0; )


Yes but this has re-arranged the natural order of the loop.

I like my "for" loops to have four phases:

(1) The "initialisation stuff" is executed first of all.

(2) The condition is tested.

(3) The body is executed.

(4) The "prepare for next iteration" stuff is executed.


Your example mixes (2) and (4), which I don't like.
 
F

Frederick Gotham

Rolf Magnus posted:

size_t is unsigned and can't have negative values. size_t(-1) tells the
compiler that you want -1 converted to size_t, IOW, it's a cast.


There's an implicit conversion from int to size_t, so no cast is required.

When dealing with intrinsic types, the following are exactly equivalent:

short(5)

(short)5

I myself prefer the latter, for two reasons:

(1) You can have types which consist of more than one word, e.g.
"unsigned short".
(2) It resembles a cast.

I dislike the former because:

(1) It looks like the construction of a user-defined class type.
(2) It doesn't resemble a cast at all.
(3) You can't use types which consist of more than one word.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,607
Members
45,240
Latest member
pashute

Latest Threads

Top