Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C style cast allow you to convert to a private base class? [duplicate]

Say we have this code

class A {
public:
    A() : x(1) {}
    virtual ~A() {}

    int x;
};

class B {
public:
    B() : y(2) {}
    virtual ~B() {}

    void g()
    {
        cout << "B::" << y << endl;
    }

    int y;
};

class C : private A, private B {
public:
    void f()
    {
        B* p = static_cast<B*>( this );
        p->g();
    }
};

int main()
{
    C c;
    ((B*)&c)->g();

    return 0;
}

The C style cast in the main function cannot be correctly expressed in terms of the C++ casts (static_cast, dynamic_cast, reinterpret_cast). But what is the reason to allow this in the first place? Doesn't it hurt encapsulation?

UPDATE This is not a duplicate of the linked question, because this question is about design decisions in C++. It does not ask what I can or cannot do with the language, it asks why certain decisions might have been made.

like image 771
unkulunkulu Avatar asked May 26 '12 21:05

unkulunkulu


People also ask

What does C-style cast do?

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).

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.

What is the difference between static_cast and Dynamic_cast in C++?

static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.

Can you convert a pointer from a derived class to its base class?

[19.4] Is it OK to convert a pointer from a derived class to its base class? Yes.


2 Answers

When a C-style pointer cast is used between pointers to a base and derived class, it behaves like a static_cast - even if the base is private.

(C-style casts between unrelated pointer types are reinterpret_casts).

The Standard says:

The conversions performed by

— a const_cast (5.2.11),

— a static_cast (5.2.9),

— a static_cast followed by a const_cast,

— a reinterpret_cast (5.2.10), or

— a reinterpret_cast followed by a const_cast,

can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

— a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;

— a pointer to member of derived class type may be explicitly converted to a pointer to member of an unambiguous non-virtual base class type;

— a pointer to an object of an unambiguous non-virtual base class type, a glvalue of an unambiguous non-virtual base class type, or a pointer to member of an unambiguous non-virtual base class type may be explicitly converted to a pointer, a reference, or a pointer to member of a derived class type, respectively.

Your situation is described in the first point, so the conversion is done by static_cast and the pointer is adjusted.

like image 121
Seth Carnegie Avatar answered Oct 13 '22 06:10

Seth Carnegie


It's because in C it was allowed to convert any pointer to any other pointer using this cast and C++ tries to be C-compatible as much as possible, but tries to do a good job to be correct when it comes to classes, so C style cast is stronger than reinterpret_cast in this situation.

like image 41
unkulunkulu Avatar answered Oct 13 '22 07:10

unkulunkulu