static_cast, dynamic_cast, reinterpret_cast

66 просмотров
Перейти к первому непрочитанному сообщению

Art Alvarado

не прочитано,
13 июл. 2004 г., 20:03:0213.07.2004
Although I think I have some idea, could someone clear something for me, as
from the BCB Help it's not so clear.
When is it requiered, recomended to use:
+ c-style cast: (void *)
+ static_cast
+ dynamic_cast
+ reinterpret_cast

I assume that structures can be casted no problem with C-style casts, but
Classes should not, correct?

For example, when I pass a TList * to a WinApi enum callback function (to
build a list of Windows for example), I should always use static_cast
correct?

Thanks,

-Art


JD

не прочитано,
13 июл. 2004 г., 21:55:3813.07.2004
"Art Alvarado" <g...@gug.net> wrote:
> [...] I assume that structures can be casted no problem with

> C-style casts, but Classes should not, correct?

Old C style casting just assigns the pointer without any
checking. As long as you *know* what you're doing, you *can*
use old style casting for everything and the program will run
as expected and perhaps a bit faster because C++ casting has
some overhead associated with it.

However, old style casting is a brute force technique (duplicated
with reinterpret_cast) that performs no checking to see if what
you're doing is valid. By not using C++ casting, you're failing
to take advantage of the built-in features and writing code that
can compile and execute but *may* be unstable or be near impossible
to debug.

> For example, when I pass a TList * to a WinApi enum callback
> function (to build a list of Windows for example), I should
> always use static_cast correct?

That's another story. When it comes to API calls, I do use C
style casting because in most of these cases, the object being
passed won't cast with any thing other than reinterpret_cast
which as I noted before is the same as old C style casting.

~ JD

Remy Lebeau (TeamB)

не прочитано,
13 июл. 2004 г., 23:33:5813.07.2004

"Art Alvarado" <g...@gug.net> wrote in message
news:40f4...@newsgroups.borland.com...

> When is it requiered, recomended to use:
> + c-style cast: (void *)

You should never use c-style casting unless there is no other choice. A
static_cast is the closest equivilent to c-style casting, except that you
get to benefit from the compile-time type checking that it offers.

> + static_cast

Any place you want to do an unconditional cast, similar to a c-style cast,
but can be validated at compile-time.

> + dynamic_cast

When you are changing a pointer from one type to another type and want to
check whether the cast succeeds. Requires polymorphic types in order to
work properly, though.

> + reinterpret_cast

Then you are changing a pointer into an integer and vice versa.

> I assume that structures can be casted no problem
> with C-style casts, but Classes should not, correct?

Not true. A c-style cast can cast just about anything, including classes
(although I would not recommend it).

> For example, when I pass a TList * to a WinApi enum callback
> function (to build a list of Windows for example), I should always
> use static_cast correct?

No. Use reinterpret_cast for that instead.


Gambit


Remy Lebeau (TeamB)

не прочитано,
13 июл. 2004 г., 23:37:3113.07.2004

"JD" <nos...@nospam.com> wrote in message
news:40f4929a$1...@newsgroups.borland.com...

> the program will run as expected and perhaps a bit
> faster because C++ casting has some overhead
> associated with it.

Only for those castings that have to be performed at run-time, such as most
uses of dynamic_cast. The rest are evaludated at compile-time and have no
run-time overhead.

> However, old style casting is a brute force technique
> (duplicated with reinterpret_cast)

A reinterpret_cast is not the closest thing to a c_style cast - a
static_cast is.

> When it comes to API calls, I do use C style casting
> because in most of these cases, the object being passed
> won't cast with any thing other than reinterpret_cast which
> as I noted before is the same as old C style casting.

You have your castings mixed up.


Gambit


Andrue Cope [TeamB]

не прочитано,
14 июл. 2004 г., 04:56:2614.07.2004
Remy Lebeau (TeamB) wrote:

> > + reinterpret_cast
>
> Then you are changing a pointer into an integer and vice versa.

Or when converting between certain pointer types:

char * wibble;
unsigned char * bibble;

wibble=static_cast<char *>( bibble );

[C++ Error] FormImageSelector.cpp(462): E2031 Cannot cast from
'unsigned char *' to 'char *'

This /always/ annoyed me so I'm going to stick my hand up and admit to
using reinterpret_cast instead. I went through a period of trying to be
a good boy and use static_cast everywhere but it seemed like every time
I used it the compiler would squawk. In the end I just gave up.

I know /why/ it doesn't want to perform the conversion but ISTM that
most type casts are used when you are changing types and to object
because of a signage issue is being pedantic or petty. I personally
think this should be a warning not an error.
--
Andrue Cope [TeamB]
[Bicester, Uk]
http://info.borland.com/newsgroups/guide.html

JD

не прочитано,
14 июл. 2004 г., 06:50:3314.07.2004

"Remy Lebeau \(TeamB\)" <gambit47...@no.spam.yahoo.com> wrote:
>
>> However, old style casting is a brute force technique
>> (duplicated with reinterpret_cast)
>
>A reinterpret_cast is not the closest thing to a c_style cast - a
>static_cast is.

As Andrue noted, static_cast does not always compile where as
a C style cast or reinterpret_cast will. In addition, there's
no checking performed with C style casting or reinterpret_cast
but there is with static_cast. How is static_cast closer to to
C style casting than reinterpret_cast?

>> When it comes to API calls, I do use C style casting
>> because in most of these cases, the object being passed
>> won't cast with any thing other than reinterpret_cast which
>> as I noted before is the same as old C style casting.
>
>You have your castings mixed up.

How?

~ JD

Chris Uzdavinis

не прочитано,
14 июл. 2004 г., 09:59:5714.07.2004
"Art Alvarado" <g...@gug.net> writes:

> Although I think I have some idea, could someone clear something for me, as
> from the BCB Help it's not so clear.
> When is it requiered, recomended to use:
> + c-style cast: (void *)
> + static_cast
> + dynamic_cast
> + reinterpret_cast
>
> I assume that structures can be casted no problem with C-style
> casts, but Classes should not, correct?

Casts are always a problem, because it means you're telling lies to
the type system. That puts the burdon of responsibility solely on
your own shoulders, and it can be hard to guarantee correctness.

C++ casts are a near complete replacement for C-style casts, and if
you can use C++ style cast, you are encouraged to always do so. The C
style cast is a very powerful tool, oftentimes doing more casting than
you actually intend, and so permissive that accidents can and do
happen much more frequently.

I first strive to never have to cast, and then always try to use C++
style casts when it's necessary.

> For example, when I pass a TList * to a WinApi enum callback function (to
> build a list of Windows for example), I should always use static_cast
> correct?

I'm not familiar with a WinAPi enum callback. :) What are you
wanting to cast the pointer to? Why?

--
Chris (TeamB);

Art Alvarado

не прочитано,
14 июл. 2004 г., 11:26:0914.07.2004

"Chris Uzdavinis (TeamB)" <ch...@uzdavinis.com> wrote in message
news:j53c3ug...@explicit.atdesk.com...

> I'm not familiar with a WinAPi enum callback. :) What are you
> wanting to cast the pointer to? Why?

Just about every function in the Windows API that requires a list to be
built, the list is not built for you. Rather than that, a function
generally called enum callback is called for each instance of what ever you
are listing.
Examples of this are: Ask Windows for a list of Windows, or a list of Audio
devices.
Windows allows you to pass a pointer (DWORD to be more precise) that then
get's passed to this enum callback function every time that it get's called.
In the case of a Window list, the enum callback function gets called once
for every window available with a handle to the window, and your DWORD that
you passed.
In just about every usefull case you would pass a Pointer (as the DWORD) to
either a link list or some List class so that at the end you have your list.
A pointer to an array will rarely be usefull unless you somehow keep a
counter in the array that let's you know how many items you have.

Anyways, I hoped that answered the question.

And thanks to everyone for the answers. I've got recasting to do. ;-)

Thanks as always!

-Art


Chris Uzdavinis

не прочитано,
14 июл. 2004 г., 12:26:4014.07.2004
"Art Alvarado" <g...@gug.net> writes:

> Windows allows you to pass a pointer (DWORD to be more precise) that
> then get's passed to this enum callback function every time that it
> get's called.

Oh, ok. That's a case where you'd use reinterpret_cast, from a
pointer to a DWORD. (And back.) The reinterpret_cast means,
basically, "These use the bitpattern from this type as if it were
actually the bitpattern for this other, unrelated type."

reinterpet_cast usually has some portability implications and/or
platform-specific dependencies. In this case, the assumptions are
that pointers and DWORDs are the same size, which in this case they
are.

--
Chris (TeamB);

Chris Uzdavinis

не прочитано,
14 июл. 2004 г., 12:20:0314.07.2004
"JD" <nos...@nospam.com> writes:

> As Andrue noted, static_cast does not always compile where as
> a C style cast or reinterpret_cast will.

That's not true either. A reinterpret_cast only works in some
situations, and a static_cast works only in some situations, and those
situations have an intersection. (That is, you can static or
reinterpret cast in some cases the same thing, but you don't always
get the same result. Also, there are cases where one works (compiles)
and the other doesn't.)

> In addition, there's no checking performed with C style casting or
> reinterpret_cast but there is with static_cast.

The only type of checking is that the cast is within the range of
allowed uses for static cast.

> How is static_cast closer to to C style casting than
> reinterpret_cast?

A C style cast is all of the C++ casts combined into one, except for
the runtime type checking of dynamic_cast.

>>> When it comes to API calls, I do use C style casting
>>> because in most of these cases, the object being passed
>>> won't cast with any thing other than reinterpret_cast which
>>> as I noted before is the same as old C style casting.
>>
>>You have your castings mixed up.
>
> How?

Here's some examples of using C style casts and what the C++ cast
should be:

char const * x = "hello";
char * unsafe = (char*) x; // const_cast
int i = (int) x; // reinterpret_cast

---

class Base { }; class Derived : public Base { };

Base * b = new Derived;
Derived * d = (Derived*) b; // static_cast

--

void foo(Base *b)
{
Derived * d = (Derived*)b; // unchecked, dangerous!!!!!!

if (Derived * d = dynamic_cast<Derived*>(b)) // safe
{
}
}


C style casts are unsafe because you can end up doing more and
different casting than you intended, with disastrous results. For
example, above I casted away constness like this:

char * unsafe = (char*) x; // const_cast

On that line, you know that x is a char const *. But suppose x were
declared higher in the file, away from the cast. Further, suppose
someone decided that they needed more data associated with the string,
so they changed the type of x to be a pointer to an object containing
the string and other stuff, to a struct like like this:

struct Stuff
{
unsigned int flags;
char const * str;
};


They edit the declaration of x such that it now looks like this:

Stuff * x = new Stuff;
x.str = "hello";
x.flags = 0;
...

Then later in your file, in an unrelated section, they forget to
change the following line, and it still compiles:

char * unsafe = (char*) x; // WHOOPS, this is reinterpreting the ptr

Now we're casting a struct pointer into a char*, and NOT casting away
constness at all. Without changing the line that involves the cast,
we still managed to change the entire meaning (and result) of the
cast. Now it's reinterpreting the address of a Stuff object as if it
were a pointer to character(s). The result will be garbled, and
possibly/likely crash. The problem will not be obvious at all, since
the problem is in a different section of code than where the acutal
changes occurred, and code that used to work suddenly breaks without a
single character changing!

Oftentimes a c style cast intention is obvious, but othertimes it's
not. Worse, it's very difficult to search source code for C style
casts with automated tools because their syntax is shared with other
language features. C++ style casts are easy to find, because they
have keywords associated that can be unambiguously searched for.

--
Chris (TeamB);

Ответить всем
Написать сообщение автору
Переслать
0 новых сообщений