Reputation: 2063
struct A{};
struct B : A{};
int main()
{
A a;
A& a_ref = a;
static_cast<B>(a); // *1
static_cast<B&>(a_ref); // *2
return 0;
}
(*1) produces an error and i understand why. (*2) compiles fine, but why? And, as long as it compiles and suppose B
contains some attributes, what if i cast a_ref
to B&
and then try to access the attributes? I think i will have an run-time error or something.
So, as i can see, there is a situation which leads to crash and there are no ways to avoid it, unlike with dynamic_cast
where one can check the result of casting for null or put code in a try-catch
region. How do i have to deal with such situation where i need to cast references and be sure that i really get the right references.
Upvotes: 17
Views: 21981
Reputation: 1815
It is important to highlight the point mentioned in dyp's comment, which is also hinted by Mike Seymour's answer.
Unlike dynamic_cast
, static_cast
doesn't perform any run-time check about the validity of the casting. If we are sure that a pointer (or reference) to a base class is pointing (or referring) to a derived object, static_cast
can be safely used to cast it to a pointer (or reference) to the derived type. The attributes of the derived class will be available. In such safe settings, using static_cast
leads to performance gains compared to using dynamic_cast
.
Upvotes: 0
Reputation: 6515
static_cast<>
will only check if the types are compatible
In case 1 types are not directly compatible since the re is no operator to describe the copy relation between A and B
In case 2 the cast is a reference cast and as far as the compiler is concerned A*
can be casted to B*
because they are compatible. The compiler will not know what the pointer a_ref
holds so that's why it allows you to use it. dynamic_cast<>
checks the class the pointer points to also.
Upvotes: 6
Reputation: 254751
(*2) compiles fine, but why?
In general, you can't check the dynamic type statically; and static_cast
doesn't do any dynamic type checking. It allows any conversion that might be valid according to the static types, including conversions that aren't valid according to the dynamic types.
what if i cast a_ref to B& and then try to access the attributes?
Undefined behaviour. If you use static_cast
, then the onus is on you to make sure the conversion is valid.
How do i have to deal with such situation where i need to cast references and be sure that i really get the right references.
For polymorphic types, use dynamic_cast
. Applied to a reference, it will throw std::bad_cast
if the conversion is not valid.
For non-polymorphic types, you're on your own.
Upvotes: 2
Reputation: 55897
From standard n3337 draft 5.2.9/2
An lvalue of type “cv1 B,” where B is a class type, can be cast to type “reference to cv2 D,” where D is a class derived (Clause 10) from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists (4.10), cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D.
In your case:
B
is class derived from A
, both are non-const, and conversion from A*
to B*
is allowed, A
is not virtual base class of D
.
Upvotes: 10