Billy ONeal
Billy ONeal

Reputation: 106530

How is dynamic_cast typically implemented?

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.

Upvotes: 8

Views: 6345

Answers (4)

Loki Astari
Loki Astari

Reputation: 264361

In some of the original compilers you are correct they used string comparison.

As a result dynamic_cast<> was very slow (relatively speaking) as the class hierarchy was traversed each step up/down the hierarchy chain required a string compare against the class name.

This leads to a lot of people developing their own casting techniques. This was nearly always ultimately futile as it required each class to be annotated correctly and when things went wrong it was nearly impossible to trace the error.

But that is also ancient history.

I am not sure how it is done now but it definitely does not involve string comparison. Doing it yourself is also a bad idea (never do work that the compiler is already doing). Any attempt you make will not be as fast or as accurate as the compiler, remember that years of development have gone into making the compiler code as quick as possible (and it will always be correct).

Upvotes: 1

Calmarius
Calmarius

Reputation: 19431

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.

Upvotes: 1

MSN
MSN

Reputation: 54554

The compiler cannot divine additional information you may have and stick it in dynamic_cast. If you know certain invariants about your code and you can show that your manual casting mechanism is faster, do it yourself. It doesn't really matter how dynamic_cast is implemented in that case.

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320381

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.

Upvotes: 6

Related Questions