Allahjane
Allahjane

Reputation: 1978

Is the behaviour for a runtime bad C-style cast defined?

Does the C++ standard define a particular behaviour if you make an old C-style cast from type A to type B where type A cannot be cast to type B and vice versa?

Would there be a known visible behavior that can be assumed to be symptom of a illegal cast in runtime using this?

Upvotes: 2

Views: 700

Answers (2)

ezaquarii
ezaquarii

Reputation: 1916

Compiler will catch some of them, but not all. Here is an example of a disastrous cast:

#include <iostream>
#include <string>

using namespace std;

class A {
public:
        A(std::string s, int x) : m_s(s), m_x(x) {} 

        void print() { cout << "A::print(): str = " << m_s << ", x = " << m_x << endl; }

private:  
        std::string m_s;
        int m_x;
};

class B {
public:
        B(int x) : m_x(x) {}
        void print() { m_x++; cout << "B::print(): x = " << m_x << endl; }

private:
        int m_x;

};

int main(int argc, char **argv) {

        A *a = new A("abc", 1);
        a->print();
        B *b = (B*)a;
        b->print();

        a->print();

        return 0;
}

Result on gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609:

A::print(): str = abc, x = 1
B::print(): x = 24828977
A::print(): str = bc, x = 1

Yes, we called B's methods on A's data, which means that our C-style cast worked as reinterpret_cast. reinterpret_cast just takes a memory region and allows you to treat is as something different. No seatbelts here.

On the other hand, if you try to compile something like this

    A a;
    B b;
    a = (A)b;
    return 0;

it will result in static_cast and compile-time error. So C-style casting result depends on context.

This is NIGHTMARE when dealing with templates and auto.

To avoid this problem, use static_cast (for compile-time checks) and dynamic_cast (for runtime checks) or reinterpret_cast (for pointers and POD), clearly stating your intent.

Upvotes: 0

Emil Laine
Emil Laine

Reputation: 42838

Only one of the four C++-style casts determines the validity of the cast at runtime, namely dynamic_cast.

A C-style cast corresponds to a combination of the other three casts (static_cast, reinterpret_cast, const_cast). The validity of those casts is determined at compile-time, or if it cannot be determined at compile-time then the cast is assumed to be valid. A C-style cast never acts like dynamic_cast.

So a C-style cast that "fails" at runtime, i.e. breaks the validity assumption, causes undefined behavior. So:

Does the C++ standard define a particular behaviour if you make an old C-style cast from type A to type B where type A cannot be cast to type B and vice versa?

No.

Would there be a known visible behavior that can be assumed to be symptom of a illegal cast in runtime using this?

No.

Upvotes: 4

Related Questions