Is the type check a mere integer comparison? Or would it make sense to have a GetTypeId
virtual function to distinguishing which would make it an integer comparison?
(Just don't want things to be a string comparison on the class names)
EDIT: What I mean is, if I'm often expecting the wrong type, would it make sense to use something like:
struct Token
{
enum {
AND,
OR,
IF
};
virtual std::size_t GetTokenId() = 0;
};
struct AndToken : public Token
{
std::size_t GetTokenId() { return AND; }
};
And use the GetTokenId
member instead of relying on dynamic_cast
.
Consider this simple hierarchy: class Base { public: virtual ~Base() { } }; class Derived : public Base { }; Trying to downcast Base* p to Derived* is possible using dynamic_cast<Derived*>(p) . I used to think dynamic_cast works by comparing the vtable pointer in p to the one in a Derived object.
The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .
If the dynamic_cast is used on pointers, the null pointer value of type new-type is returned. If it was used on references, the exception std::bad_cast is thrown.
Note. You are permitted to use dynamic_cast without --rtti in cases where RTTI is not required, such as dynamic cast to an unambiguous base, and dynamic cast to (void *) . If you try to use dynamic_cast without --rtti in cases where RTTI is required, the compiler generates an error.
The functionality of the dynamic_cast
goes far beyond a simple type check. If it was just a type check, it would be very easy to implement (something like what you have in your original post).
In addition to type checking, dynamic_cast
can perform casts to void *
and hierarchical cross-casts. These kinds of casts conceptually require some ability to traverse class hierarchy in both directions (up and down). The data structures needed to support such casts are more complicated than a mere scalar type id. The information the dynamic_cast
is using is a part of RTTI.
Trying to describe it here would be counterproductive. I used to have a good link that described one possible implementation of RTTI... will try to find it.
I don't know the exact implementation, but here is an idea how I would do it:
Casting from Derived*
to Base*
can be done in compile time. Casting between two unrelated polimorphic types can be done in compile time too (just return NULL).
Casting from Base*
to Derived*
needs to be done in run-time, because multiple derived classes possible. The identification of dynamic type can be done using the virtual method table bound to the object (that's why it requires polymorphic classes).
This VMT probably contains extra information about the base classes and their data offsets. These data offsets are relevant when multiple inheritance is involved and is added to the source pointer to make it point to the right location.
If the desired type was not found among the base classes, dynamic_cast
would return null.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With