[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-devel
Subject: Casts (was: Re: Strange effect...)
From: Johannes Sixt <Johannes.Sixt () telecom ! at>
Date: 1997-12-23 18:32:00
[Download RAW message or body]
On Tue, 23 Dec 1997, Prasanth Kumar wrote:
>Johannes Sixt wrote:
><snip>
>> Casts are a hack. Always. Well, almost always.
>>
>> If you really want to do it with casts, then do it the C++ way:
>>
>> printf("A -> %s\n\n", static_cast<const char *>(A));
>>
>> C-style casts are a hack in C++. Always. Really.
>>
>> -- Hannes
>
>I am not familiar with the new C++ way of doing casts but...
>what is the new way not a hack compared to the C-style?
C++ introduces four new operators that do type casts:
static_cast
const_cast
reinterpret_cast
dynamic_cast
as well as a functional notation for type conversion.
The differences are:
- they are safer because you can't cast anything to everything,
- it's more obvious which cast is intended,
- you can search the source file for casts (have you ever tried to search for
C-style casts?),
- they are more powerful.
A const_cast can be used to remove const specifiers from pointers:
void f(const T* pct) {
T* pt = const_cast<T*>(pct);
}
It works also for references, but it can't perform other casts.
A static_cast basically can do only casts from type T1 to T2 where
there's an implicit cast from T2 to T1:
struct B { int i; };
struct D : B {};
D d;
B* pb = &d; // implicit cast D* -> B*
D* pd = static_cast<D*>(pb); // cast needed: B* -> D*
Note that static_cast can't be used for unrelated pointer types:
int* pi = static_cast<int*>(pb); // error since int* and B* are unrelated
The following would work, however, because pointers can be cast to void*:
int* pi = static_cast<int*>(static_cast<void*>(pb));
but it disregards alignment restrictions.
A reinterpret_cast does what it's name suggests: it reinterprets values:
int* pi = reinterpret_cast<int*>(errno);
Most conversions that can be done with reinterpret_cast have defined behavior
only if the value is converted back with a reinterpret_cast to the original
type. The intent is that the result of a reinterpret_cast is "unsurprising to
those how know the addressing structure of the underlying machine."
A dynamic_cast is like a static_cast which does runtime-typechecking:
struct B { };
struct D : B {};
D d;
B* pb = &d;
dynamic_cast<D*>(pb); // returns pointer to d
B b;
pb = &b;
dynamic_cast<D*>(pb); // returns NULL, since pb doesn't point to a D
dynamic_cast obviously requires runtime type information.
The functional notation of cast is just a different syntax for C-Style casts:
enum E { e1, e2, e3 };
E err = E(errno); // equivalent to (E) errno
int pi100 = int(100.0*3.14159);
Looks like a constructor call, doesn't it?
Finally, the semantics of a C-style cast is the first of:
- a const_cast,
- a static_cast,
- a static_cast, followed by a const_cast,
- a reinterpret_cast,
- a reinterpret_cast, followed by a const_cast
that would work.
-- Hannes
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic