static_cast and virtual base classes

Discussion in 'C++' started by Dave Rahardja, May 24, 2006.

  1. Is it safe to use static_cast to downcast from a virtual base class?

    For example,

    class V {};
    class A: public virtual V {};
    class B: public virtual V {};
    class C: public A, public B;

    void fn(V& v)
    {
    A& a = static_cast<A&>(v);
    B& b = static_cast<B&>(v);
    C& c = static_cast<C&>(v);
    }

    Assuming that the parameter to fn() is an instance of C, of course.

    Or do I have to use dynamic_cast? When is static_cast not sufficient?

    -dr
    Dave Rahardja, May 24, 2006
    #1
    1. Advertising

  2. Dave Rahardja wrote:
    > Is it safe to use static_cast to downcast from a virtual base class?


    What do you mean by "safe"? As in "nobody is going to get killed"?

    > For example,
    >
    > class V {};
    > class A: public virtual V {};
    > class B: public virtual V {};
    > class C: public A, public B;
    >
    > void fn(V& v)
    > {
    > A& a = static_cast<A&>(v);
    > B& b = static_cast<B&>(v);
    > C& c = static_cast<C&>(v);
    > }
    >
    > Assuming that the parameter to fn() is an instance of C, of course.
    >
    > Or do I have to use dynamic_cast? When is static_cast not sufficient?


    'static_cast' is sufficient when your compiler says it's sufficient. Trust
    your compiler, it knows (in most cases).

    BTW, you can't use 'dynamic_cast' here, your classes are not polymorphic.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 24, 2006
    #2
    1. Advertising

  3. On Wed, 24 May 2006 09:06:41 -0400, "Victor Bazarov" <>
    wrote:

    >Dave Rahardja wrote:
    >> Is it safe to use static_cast to downcast from a virtual base class?

    >
    >What do you mean by "safe"? As in "nobody is going to get killed"?


    By "safe" I mean "yield defined behavior".

    >
    >> For example,
    >>
    >> class V {};
    >> class A: public virtual V {};
    >> class B: public virtual V {};
    >> class C: public A, public B;
    >>
    >> void fn(V& v)
    >> {
    >> A& a = static_cast<A&>(v);
    >> B& b = static_cast<B&>(v);
    >> C& c = static_cast<C&>(v);
    >> }
    >>
    >> Assuming that the parameter to fn() is an instance of C, of course.
    >>
    >> Or do I have to use dynamic_cast? When is static_cast not sufficient?

    >
    >'static_cast' is sufficient when your compiler says it's sufficient. Trust
    >your compiler, it knows (in most cases).
    >
    >BTW, you can't use 'dynamic_cast' here, your classes are not polymorphic.


    D'oh, my bad. Yes, assume there are pure virtual functions in V that A, B, and
    C are providing.

    -dr
    Dave Rahardja, May 24, 2006
    #3
  4. Dave Rahardja

    Greg Guest

    Dave Rahardja wrote:
    > Is it safe to use static_cast to downcast from a virtual base class?
    >
    > For example,
    >
    > class V {};
    > class A: public virtual V {};
    > class B: public virtual V {};
    > class C: public A, public B;
    >
    > void fn(V& v)
    > {
    > A& a = static_cast<A&>(v);
    > B& b = static_cast<B&>(v);
    > C& c = static_cast<C&>(v);
    > }
    >
    > Assuming that the parameter to fn() is an instance of C, of course.
    >
    > Or do I have to use dynamic_cast? When is static_cast not sufficient?


    You must a dynamic_cast when casting from a virtual base class to a
    derived class (or the other way around). Using a static_cast for such a
    conversion would lead to undefined behavior.

    Greg
    Greg, May 24, 2006
    #4
  5. Dave Rahardja

    Noah Roberts Guest

    Greg wrote:

    > You must a dynamic_cast when casting from a virtual base class to a
    > derived class (or the other way around). Using a static_cast for such a
    > conversion would lead to undefined behavior.


    I don't believe that is accurate; if so please provide the clause
    because there are many, many expert written books that show how to
    write a safe and fast "polymorphic_cast" by performing a dynamic cast
    and testing the result when in debug build but static cast otherwise.
    Noah Roberts, May 24, 2006
    #5
  6. Noah Roberts wrote:
    > Greg wrote:
    >
    > > You must a dynamic_cast when casting from a virtual base class to a
    > > derived class (or the other way around). Using a static_cast for such a
    > > conversion would lead to undefined behavior.

    >
    > I don't believe that is accurate; if so please provide the clause


    "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 not a virtual base
    class of D. The result is an lvalue of type "cv2 D." If the lvalue
    of type "cv1 B" is actually a sub-object of an object of type D,
    the lvalue refers to the enclosing object of type D. Otherwise, the
    result of the cast is undefined." (5.2.9§5)


    Jonathan
    Jonathan Mcdougall, May 25, 2006
    #6
  7. Dave Rahardja

    Greg Guest

    Noah Roberts wrote:
    > Greg wrote:
    >
    > > You must a dynamic_cast when casting from a virtual base class to a
    > > derived class (or the other way around). Using a static_cast for such a
    > > conversion would lead to undefined behavior.

    >
    > I don't believe that is accurate; if so please provide the clause
    > because there are many, many expert written books that show how to
    > write a safe and fast "polymorphic_cast" by performing a dynamic cast
    > and testing the result when in debug build but static cast otherwise.


    A dynamic_cast can indeed be safely replaced with a static_cast to
    convert from a derived to a base class - just as long as there is no
    virtual inheritance involved. And given how rare virtual base classes
    are in practice - it is not surprising that the fact that a
    dynamic_cast is required in this case - rarely comes up.

    The relevant clauses are §5.2.9/2 and §5.2.9/9 of which I quote the
    first one here:

    "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 not a virtual base class of D.
    ....Otherwise, the result of the cast is undefined."

    Note the qualification: "B is not a virtual base class of D".

    Greg
    Greg, May 25, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Winter
    Replies:
    9
    Views:
    615
    Michael Winter
    Sep 24, 2003
  2. tomek
    Replies:
    2
    Views:
    671
    Andrey Tarasevich
    Dec 1, 2003
  3. tomek
    Replies:
    3
    Views:
    742
    David Fisher
    Nov 30, 2003
  4. Bo Peng
    Replies:
    11
    Views:
    1,080
    Victor Bazarov
    Oct 20, 2006
  5. junyangzou
    Replies:
    13
    Views:
    256
Loading...

Share This Page