21
votes

Consider:

class base
{
    base();
    virtual void func();
}

class derived : public base
{
    derived();
    void func();
    void func_d();
    int a;
}


main
{
    base *b = new base();
    sizeof(*b); // Gives 4.
    derived * d = static_cast<derived*>(b);
    sizeof(*d); // Gives 8- means whole derived obj size..why?
    d->func_d();
}

In the above code I did downcasting of a base pointer which points to base object to derived class pointer. I am wondering how the derived pointer has the whole derived class object. I can call the derived class function (declared in derived class only). I did not get the concept here.

3
Please make an effort to post compilable code.user2100815

3 Answers

23
votes

Using static_cast to cast an object to a type it doesn't actually have yields undefined behavior. The symptoms of UB vary widely. There's nothing that says UB can't allow the derived member function to be called successfully (but there's nothing that guarantees that it will, so don't count on it).

Here is the rule for downcasting using static_cast, found in section 5.2.9 ([expr.static.cast]) of the C++ standard (C++0x wording):

A prvalue of type "pointer to cv1 B", where B is a class type, can be converted to a prvalue of type "pointer 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 null pointer value is converted to the null pointer value of the destination type. If the prvalue of type "pointer to cv1 B" points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.

9
votes

The only cast that does runtime checking is dynamic_cast<>(). If there is any possibility that a cast will not work at runtime then this cast should be used.

Thus casting from leaf->root (up casting) static_cast<>() works fine.
But casting from root->leaf (down casting) is dangerous and (in my opinion) should always be done with dynamic_cast<>() as there will be dependencies on run-time information. The cost is slight, but always worth paying for safety.

8
votes

sizeof exists at compile-time. It neither knows nor cares that at run-time, your base object doesn't point to a derived. You are attempting to influence compile-time behaviour with a run-time variable, which is fundamentally impossible.