Why does C style cast allow you to convert to a pr

2019-01-24 12:03发布

问题:

This question already has an answer here:

  • Can I cast a derived class to a private base class, using C-style cast? 3 answers

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.

回答1:

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.



回答2:

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.



回答3:

A C-style cast allows you to convert any type to any other type. You can do (std::istream*)&c if you'd like, but it's not recommended.