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.
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).
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.
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.
[19.4] Is it OK to convert a pointer from a derived class to its base class? Yes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With