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