What is the purpose to have const_cast or reinterpret_cast?

P

PowerStudent

Hy,

I'm coming from my happy Java environment and I am trying to
understand some aspects of the battle field that is C++.

I'm currently reading "Thinking in C++" and have reached the part
where Bruce Eckel introduces the possible casts C++ provides.

I can easily understand the need for the normal cast (static_cast),
but why do you need const_cast or reinterpret_cast, when they cause so
much trouble?
I mean, if I or somebody else declare something has to be constant or
of a certain type, I/he/she/it don't/doesn't want that these
properties are just changed, because we* have thought this through
beforehand.

Hope I get a lot of nice answers.

Greetings from Germany

P.S. sorry for my english

*I/he/she/it
 
I

Ian Collins

Hy,

I'm coming from my happy Java environment and I am trying to
understand some aspects of the battle field that is C++.

I'm currently reading "Thinking in C++" and have reached the part
where Bruce Eckel introduces the possible casts C++ provides.

I can easily understand the need for the normal cast (static_cast),
but why do you need const_cast or reinterpret_cast, when they cause so
much trouble?

Well const_cast does have it's uses. One of this was discussed here in
the past week or so - implementing a non-const member function using the
const version rather than duplicating the code. For example in a
generic value class I use, there is a fairly long conversion operator

template <typename T> const T& as() const;

and the non-const version is written as

template <typename T> T& as()
{
return const_cast<T&>(const_cast<const Value*>(this)->as<T>());
}

The inner cast to a const Value* causes the const member to be called
and the outer cast converts the returned const T& to a T&.

reinterpret_cast is probably the least used of all the casts and is as
close as C++ casts get to a C style cast. You will (should) only see it
in low level code.
 
F

Francesco S. Carta

Hy,

I'm coming from my happy Java environment and I am trying to
understand some aspects of the battle field that is C++.

I'm currently reading "Thinking in C++" and have reached the part
where Bruce Eckel introduces the possible casts C++ provides.

I can easily understand the need for the normal cast (static_cast),
but why do you need const_cast or reinterpret_cast, when they cause so
much trouble?
I mean, if I or somebody else declare something has to be constant or
of a certain type, I/he/she/it don't/doesn't want that these
properties are just changed, because we* have thought this through
beforehand.

The purpose of those ugly and long casts is double:
- make the programmers' intention explicit
- ensure that programmers aren't forced to use C-style casts to achieve
what can be already done in C

Backwards compatibility with and equal powers to C are two pillars of
the C++ language, and those casts represent one of the many ways C++
achieves that purpose.

That said, you're perfectly right to say that if someone declares
something as const, others shouldn't mindlessly cast the const away, but
sometimes you have no other choice but "arrange" the "stuff" so that,
for example, you can pass it to some pre-existing library which already
does its work fine, but which, eventually, happens to have been written
in C or in some past flavor of C++.

Also, notice that the need for those casts is almost unnecessary when
doing "good" C++. They're mostly needed for legacy and for very low
level code - or for hacking your way around some bad C++ interface that
you cannot modify or that you don't have the time to fix ;-)

And again, as it happens with C, casts are just another powerful bullet
you can shoot at the correct target or at your feet, so the point is
mostly about having a good aim ;-)
 
M

mingze zhang

Hy,

I'm coming from my happy Java environment and I am trying to
understand some aspects of the battle field that is C++.

I'm currently reading "Thinking in C++" and have reached the part
where Bruce Eckel introduces the possible casts C++ provides.

I can easily understand the need for the normal cast (static_cast),
but why do you need const_cast or reinterpret_cast, when they cause so
much trouble?
I mean, if I or somebody else declare something has to be constant or
of a certain type, I/he/she/it don't/doesn't want that these
properties are just changed, because we* have thought this through
beforehand.

Hope I get a lot of nice answers.

Greetings from Germany

P.S. sorry for my english

*I/he/she/it

reinterpret_cast is really low level thing and is mostly compiler
defined (the c++ standard doesn't say too much on how reinterpret_cast
shall behave).

For example, it is quite often in C to combine two bytes char into a
16 bytes value.

typedef char int8_t;
typedef short int16_t;
int8_t x[2] = { 1, 2 };
int16_t a = x[0] | (x[1] << 8);

In C, you can write the above conversion directly in the following
form,

int16_t a = *(int16_t *)x;

The result of a depends on the compiler and machine (little or big
endian)

In C++, you can write
int16_t a = *reinterpret_cast<int16_t *>(x);
 
J

Joshua Maurice

Hy,

I'm coming from my happy Java environment and I am trying to
understand some aspects of the battle field that is C++.

I'm currently reading "Thinking in C++" and have reached the part
where Bruce Eckel introduces the possible casts C++ provides.

I can easily understand the need for the normal cast (static_cast),
but why do you need const_cast or reinterpret_cast, when they cause so
much trouble?
I mean, if I or somebody else declare something has to be constant or
of a certain type, I/he/she/it don't/doesn't want that these
properties are just changed, because we* have thought this through
beforehand.

Hope I get a lot of nice answers.

A lot of this has been mentioned else-thread, but here's my specific
take on it:

C is meant, in one form or another, as a portable assembly language,
with some efficient "syntactic sugar". Specifically, it is envisioned
that there is an obvious, one to one translation from C code to
assembly for most platforms which will perform about as well as the
handwritten assembly. This is largely the case (though with platform
specific knowledge and hackery, or hardware specific assembly, yes you
can do better than C). C comes with syntactic sugar, such as functions
and structs, which is meant as literal syntactic sugar: easily
translatable to other obvious language constructs without additional
execution time nor execution space costs.

C++ is meant in many ways to be a better C, or at least that's one of
its explicit design goals. As such, you need to be able to do weird
things like take a memory address, do int arithmetic on it, do some
double arithmetic on it, then treat it as a pointer and fetch the
pointed-to memory location. Generally such things are not required by
nearly all C and C++ programs, but it's the C and C++ philosophy at
some level to be a highly efficient portable assembly language. Also,
as C++ is meant to be a better C, C++ tries as best as it can to be
backwards compatible with C.

So, C let's you do this weird typecasting, thus C++ should also let
you do this weird typecasting. The designers of C++ saw that such a
certain subsets of typecasting is quite usually a bad idea. However,
there are good reasons to do such weird typecasting in C and C++,
usually to work with an existing C library interface (ex: POSIX) which
requires such typecasting (ex: you're required to reinterpret_casting
or equivalent the result of dlsym), to be platform specific stuff like
write device drivers, or to do generics in C and sometimes C++ (but C+
+ has templates which are usually a better solution).

So, these certain subsets of typecasting are quite usually bad and not
intended, but the syntax makes it easy for the developer to do, so a
new syntax was invented which easily allows developers to do all of
their old things but in a not "ambiguous" way - the new named casts
static_cast, const_cast, and reinterpret_cast. The new names are also
easier to grep for, or visually see. It's for the developer's benefit,
to allow him to help prevent shooting himself in the foot through a
typo or equivalent.

Also, with the introduction of multiple inheritance and virtual
inheritance, under the "normal" implementation, typecasting in C++ can
change the actual memory bit patterns. Before, a C cast from a pointer
to an integer (of sufficient size) generally did not change the
underlying bit patterns. However, to implement multiple inheritance
and virtual inheritance, pointer casting in C++ can change the actual
bit pattern of the pointer. Static offset calculations are needed to
adjust the pointer when working with multiple inheritance under the
"normal" implementation. Ex:
class A;
class B;
B* get_some_b_object();
B* b = get_some_b_object();
A* a = (A*)b;
Suppose the developer knows that A is a subtype of B, and he knows
that the object returned is actually an "A" object, so this cast
"makes sense". However, if the types A and B are only forward
declared, then the cast will be treated as a reinterpret_cast, which
will highly likely not change the bit patterns involved, likely
breaking the example if this has multiple and/or virtual inheritance.
(It's also (??) formally undefined behavior.) The problem is that C++
effectively defines the C-style cast as having two different behaviors
depending on whether the types are related through an inheritance
relationship at the point of the cast. If someone later adds or
removes the definitions of A and B from scope (such as adding or
removing a header in a header in a header), then the C-style cast may
silently change behavior and break the program. The static_cast has
only one meaning, and it will only compile when the definitions of A
and B are in scope, which is likely what the programmer wants.

So, to summarize, why does C++ have the "evil" casts?
- Backwards compatible with C as an explicit design goal.
- C++ designers also recognized that these "evil" casts sometimes have
legitimate uses.
- C++ designers also recognized that a more clear syntax for casting
would help developers not shoot themselves in the foot, and for
auditing, code review, etc.
- C++ designers also recognized that the C-style cast has a new
ambiguity in C++ which it did not have in C, so new named casts help
developers not shoot themselves in the foot, and for auditing, code
review, etc.
 

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,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top