fogbit
fogbit

Reputation: 2063

c++ static_cast and references

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

Answers (5)

Hari
Hari

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

Raxvan
Raxvan

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

Mike Seymour
Mike Seymour

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

ForEveR
ForEveR

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

Johny
Johny

Reputation: 1997

This is one of the reasons why I use boost::polymorphic_downcast (doc) - in debug it uses dynamic_cast followed by assert and in release it is static_cast, so no performance hit.

Upvotes: 6

Related Questions