8

It is said that C-style cast just tries to apply different combination of C++ casts and the first allowed combination is used. However, I have a feeling that I heard that there are situations that only C-style cast can handle, while none of combination of C++ casts are allowed.

Am I wrong? Is that true that any C-style cast in any context (in C++) can be replaced with a proper combination of C++ casts?

UPD Thanks to Cheers and hth. - Alf, we have an example that C++ casts cannot handle in the meaning they cannot produce defined and expected behavior. Advanced question is to provide an example which C++ casts cannot handle meaning it cannot be even compiled?

Community
  • 1
  • 1
Mikhail
  • 20,685
  • 7
  • 70
  • 146

1 Answers1

11

Cast to inaccessible base can only be expressed as a C style cast (one of the syntactic variants). In that context it is equivalent to a static_cast, which may change the address, except that static_cast can't access the base.

Example:

struct Base
{
    int x = 42;
};

struct Oh_my
    : private Base
{
    virtual ~Oh_my() {}
};

#include <iostream>
using namespace std;
auto main() -> int
{
    Oh_my o;
    cout << "C cast: " << ((Base&)o).x << endl;
    cout << "reinterpret_cast: " << reinterpret_cast<Base&>(o).x << endl;
}

Output with MingW g++ in Windows 7:

C cast: 42
reinterpret_cast: 4935184

But since it's pretty Undefined Behavior, the last output operation could just crash.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • A sample would help. My first thought was that `reinterpret_cast` can do anything, but I eventually thought of a case where `reinterpret_cast` might require pointer arithmetic and knowledge of compiler internals to work. Was that what you were thinking, or do you have an even better example? – Mooing Duck Nov 24 '15 at 18:20
  • I'll have to write one and get another cup of coffee. But, OK. :) – Cheers and hth. - Alf Nov 24 '15 at 18:21
  • 1
    @MooingDuck `struct A { int i; }; struct B { int i; }; struct C : private A, private B { };`, then doing a C-style cast from `C *` to either `A *` or `B *` will work, whereas a `static_cast` will fail, and a `reinterpret_cast` will give the wrong result for at least one of them. –  Nov 24 '15 at 18:24
  • 1
    @hvd: right, that's the case I thought of. `reinterpret_cast` can work, but it requires pointer arithmetic and knowledge of compiler internals, so I would count that as "C++ casts can't handle". – Mooing Duck Nov 24 '15 at 18:25
  • 2
    What is the purpose of the virtual destructor? If I remove that, I get the same output with both casts. – Emil Laine Nov 24 '15 at 18:35
  • 4
    It's the same as with @hvd's multiple inheritance, to *practically* ensure that the (or at least one) base sub-object is not at the same address as the most derived object. – Cheers and hth. - Alf Nov 24 '15 at 18:38
  • Brilliant. Let's go to the level two. An example that C++ casts cannot even _compile_? :) – Mikhail Nov 24 '15 at 20:00
  • 1
    @Mikhail: Pretty sure `reinterpret_cast` will _compile_ for anything C will cast, assuming the types are the same for each. – Mooing Duck Nov 24 '15 at 21:14