Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this downcasting undefined?

Consider this example, where the base class has some data members, while derived one only provides an additional method:

struct TestBase
{
    int x;
    TestBase() : x(5) {}
};

struct TestDerived : public TestBase
{
    void myMethod()
    {
        x=8;
    }
};

int main()
{
    TestBase b;
    TestDerived& d=static_cast<TestDerived&>(b);
    d.myMethod();
}

This is downcasting to wrong type, so AFAIU it has undefined behavior. But are there maybe some exceptions to such cases as this, where the derived class' layout is identical to that of base class?

like image 685
Ruslan Avatar asked Nov 08 '15 18:11

Ruslan


1 Answers

From the standard (emphasis mine):

§5.2.9 Static cast [expr.static.cast] ...

(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 from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists, 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. The result has type “cv2 D.” An xvalue of type “cv1 B”may be cast to type “rvalue reference to cv2 D” with the same constraints as for an lvalue of type “cv1 B.” If the object of type “cv1 B” is actually a subobject of an object of type D, the result refers to the enclosing object of type D. Otherwise, the behavior is undefined.

My first guess was that the cast should be valid in this case, because I got confused by the term subobject.

Now (thanks to @T.C. and @M.M), it is obvious that the behavior is undefined in this case.

The cast would be valid in the following example:

int main()
{
    TestDerived d;
    TestBase &br = d; // reference to a subobject of d
    TestDerived &dr = static_cast<TestDerived&>(br);  // reference to the original d object
    d.myMethod();
}

Here, an object of class TestDerived (d) will have a subobject of class TestBase (br is a reference to this object).

like image 106
sergej Avatar answered Oct 10 '22 11:10

sergej