static_cast and virtual base classes

D

Dave Rahardja

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
 
V

Victor Bazarov

Dave said:
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
 
D

Dave Rahardja

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

By "safe" I mean "yield defined behavior".
'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
 
G

Greg

Dave said:
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
 
N

Noah Roberts

Greg said:
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.
 
J

Jonathan Mcdougall

Noah said:
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
 
G

Greg

Noah said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top