Re: dynamic_cast does not work as specified
On Mon, 12 Jan 2009 04:59:06 -0500, Joseph M. Newcomer
<newcomer@flounder.com> wrote:
It is not at all clear from the documentation that expression is required to be in the
inheritance chain of type-id
Was that a rimshot I heard in the distance? :)
yes, I see now that I can cast to a void*; I'd read it the
other way...)
Consider if I did
SubThing * p = (SubThing*)pHint;
then p is a pointer to an object (ideally) of type SubThing.
Indeed, pHint had better be of a type that can be legally converted to
SubThing* via a C-style cast.
But I wanted the additional
typecheck to be done to tell me if the thing that is pointed to is of type (SubThing).
If you want to use dynamic_cast, but you're coming from void*, or T* where
T is a lie, as it in your example where MFC makes you use CObject* as a
generic pointer type, you first have to cast the pointer to a known type
that has RTTI information attached, i.e. a type that has a vtbl, i.e a type
that has a virtual function, the latter being the real requirement. That
initial cast cannot be a dynamic cast. Instead, it must be a /valid/
reinterpret_cast. Then you can dynamic_cast the result of the
reinterpret_cast to another type.
What is interesting is that casting to LPVOID makes it work; this points out once again
the horror of OnUpdate/UpdateAllViews using a CObject* instead of an LPVOID.
It is rather presumptuous.
My suspicion
was that since CObject* was not part of the hierarchy it was failing, but the
documentation does not at all make this clear. The phrase at the end
If type-id is a pointer to an unambiguous accessible direct or indirect base class of
expression, a pointer to the unique subobject of type-id is the result
is not stated as a limitation, but what will happen if typeid is a superclass of
expression's type; it does not suggest what happens if typeid is or is not a subclass of
expression's type.
You can also perform a cross-cast, e.g. cast between X and Y in this MI
hierarchy:
#include <stdio.h>
struct X { virtual void f() {} };
struct Y {};
struct Z : X, Y {};
int main()
{
Z z;
X* p = &z;
Y* q = dynamic_cast<Y*>(p); // q points to z's Y.
X x;
X* r = &x;
Y* s = dynamic_cast<Y*>(r); // s is set to NULL.
printf("%p, %p, %p\n",
(void*) static_cast<Y*>(&z),
(void*) q,
(void*) s);
}
X>cl -W4 a.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for
80x86
X>a
0012FF30, 0012FF30, 00000000
That's why I spoke in terms of the "inheritance graph" instead of base and
derived classes.
--
Doug Harrison
Visual C++ MVP