Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ static_cast downcast validity [duplicate]

Tags:

c++

Is this static_cast downcast valid?

// non-virtual, may be non-trivially copyable
struct Base{
    int m_object;
};

// Derived class have only non-virtual functions
struct A : Base{
    void arggh(){
        std::cout << "Arrghh " << m_object;
    }
};

int main() {
    Base base{190};
    A& a = static_cast<A&>(base);
    a.arggh();
    return 0;
}

I mean, CREATE base class, and then cast to derived.

Live

like image 357
tower120 Avatar asked Dec 23 '22 12:12

tower120


2 Answers

static_cast for performing downcast does not perform any safety checks. Since it's possible for a Base& to be referencing an instance of A, the cast proceeds and since it's NOT actually referencing an A, we enter undefined behavior territory*.

A dynamic_cast on the other hand is safer. It will perform a check and throw an exception in the case of reference casting, or return nullptr in the case of pointer casting.

However, since your base class lacks any virtual functions, dynamic_cast is impossible, so you'd need to modify it with at least a virtual destructor:

class Base{
public:
    int m_object;
    virtual ~Base()=default;
};

Now if we tried to cast:

A* a = dynamic_cast<A*>(&base);
if (a)
    a->arggh();
else
    std::cout << "null\n";

Our output would be

null


*Relevant standardese can be found in [expr.static.cast]:

[for a cast like static_cast<D&>(b) where b is an instance of a base class for D], If the object of type “cv1 B” is actually a base class subobject of an object of type D, the result refers to the enclosing object of type D. Otherwise, the behavior is undefined.

Relevant standardese at [expr.dynamic.cast]

The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws an exception of a type that would match a handler of type std::bad_cast

like image 141
AndyG Avatar answered Jan 05 '23 00:01

AndyG


No.

Not all Base objects are of type A1, although the converse is true, and a static_cast would work in that direction.


1Another translation unit might have a class that inherits from Base.

like image 20
Bathsheba Avatar answered Jan 05 '23 01:01

Bathsheba