In concept, dynamic_cast
can work across module boundaries. But, some compilers/linkers cut corners in the name of performance. One of the ways to improve performance when loading shared libraries is to make as few symbols visible to other libraries as possible. This reduces the amount of work the loader has to do because it doesn't have to resolve as many symbols. RTTI symbols are on the chopping block and are among those not exposed to other modules by default. GCC's documentation describes this and the workaround here.
Unfortunately, this makes things a mess when it comes to RTTI. The module that constructed an object and the one performing the dynamic_cast
might hold their own, otherwise identical, RTTI symbols for a type. This makes them appear as different types when the dynamic_cast
is performed in a different module, causing dynamic_cast
to unexpectedly return nullptr
, or throw std::bad_cast
for references.
Special care is required when linking and when calling dlopen()
for the loader to know to resolve RTTI symbols between modules on module load.
Also, historically Qt has supported platforms which either do not support RTTI, or where RTTI would have too much of an overhead. So, qobject_cast
was invented to remove the reliance on RTTI altogether while still providing a way to cast between polymorphic types.
To answer your other questions:
- You can use
dynamic_cast
anywhere RTTI is available but dynamic linking can make this difficult.
- Virtual functions work fine in these scenarios as the loader will resolve the symbols of functions.