Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need clarifications in C-style, reinterpret, and const casts

Am I right in assuming that C-style casts (which are discouraged) are nothing but reinterpret_casts? Using the latter is visually striking and easy to search when looking for nasty casts, and hence it's recommended over C-style casts?

If casting away const using const_cast and writing to a originally const object is undefined, what is the purpose of const_cast?

Note: I know that Bjarne rightly condemns casting operations that they are unsafe and even goes to the extent of stating "An ugly operation should have an ugly syntactic form." and hence the verbosity of casting operators in C++. So I'll try to minimize their usage. Promise. :)

like image 406
legends2k Avatar asked Feb 27 '10 07:02

legends2k


People also ask

Can you cast something as const in C?

Const casts are only available in C++. Const casts are used to strip the const-ness or volatile-ness from a variable.

What is the difference between static cast and reinterpret cast?

static_cast only allows conversions like int to float or base class pointer to derived class pointer. reinterpret_cast allows anything, that's usually a dangerous thing and normally reinterpret_cast is rarely used, tipically to convert pointers to/from integers or to allow some kind of low level memory manipulation.

What is C-style cast?

C-style casts can be used to convert any type into any other type, potentially with unsafe results (such as casting an integer into a pointer type). (<type>)<value> This example casts an int to a double for the purpose of avoiding truncation due to integer division: double result = (double)4/5; Popular pages.

Why is static_cast better than C-style cast?

In short: static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. Intentions are conveyed much better using C++ casts.


1 Answers

No. A C cast can do the equivalent of a const_cast, a static_cast, a reinterpret_cast, or a combination thereof. In case that wasn't quite enough, it can also do at least one minor trick that no combination of the newer casts can do at all!

You can use const_cast with defined results if the original variable is defined without const, but all you have is a const pointer or reference to that object. OTOH, if you think you have a good reason to use a const_cast, chances are that you should really look up mutable instead.

Edit: I suppose I should have said it right off, but a C-style cast can convert to an an inaccessible base class. For example, consider something like:

[Edit: I'm updating the code to something that'll compile and (usually) demonstrate problem. ]

#include <iostream>

class base1 {
public:
    virtual void print() { std::cout << "base 1\n"; }
};

class base2 {
public:
   virtual void print() { std::cout << "base 2\n"; }
};

class derived : base1, base2 {}; // note: private inheritance

int main() {    
    derived *d = new derived;
    base1 *b1 = (base1 *)d;    // allowed
    b1->print();    // prints "base 1"
    base2 *b2 = (base2 *)d;    // also allowed
    b2->print();    // prints "base 2"

//    base1 *bb1 = static_cast<base *>(d);  // not allowed: base is inaccessible

    // Using `reinterpret_cast` allows the code to compile.
    // Unfortunately the result is different, and normally won't work. 
    base1 *bb2 = reinterpret_cast<base1 *>(d);
    bb2->print();   // may cause nasal demons.

    base2 *bb3 = reinterpret_cast<base2 *>(d); 
    bb3->print();   // likewise
    return 0;
}

The code using the reinterpret_casts will compile -- but attempting to use the result (of at lest one of the two) will cause a major problem. The reinterpret_cast takes the base address of the derived object and attempts to treat it as if it was the specified type of base object -- and since (at most) one base object can actually exist at that address, trying to treat it as the other can/will cause major problems. Edit: In this case, the classes are essentially identical except for what they print, so although anything could happen, with most compilers, both of the last two will print out "base 1". The reinterpret_cast takes whatever happens to be at that address and tries to use it as the specified type. In this case, I've (tried to) make that do something harmless but visible. In real code, the result probably won't be so pretty.

The C-style cast will work like a static_cast would if the code had used public inheritance instead of private -- i.e. it's aware of where in the derived class each base class object "lives", and adjusts the result, so each resulting pointer will work because it's been adjusted to point at the right place.

like image 123
Jerry Coffin Avatar answered Sep 30 '22 08:09

Jerry Coffin