28

C++ code can be compiled with run-time type information disabled, which disables dynamic_cast. But, virtual (polymorphic) methods still need to be dispatched based on the run-time type of the target. Doesn't that imply the type information is present anyway, and dynamic_cast should be able to always work?

Bart van Heukelom
  • 43,244
  • 59
  • 186
  • 301
  • 1
    My guess would be that the vtable is still present but as it doesn't contain any type information (only function pointers) virtual functions will still work. – Simon Gibbons Dec 18 '15 at 10:48
  • 1
    Possible duplicate of http://stackoverflow.com/questions/4486609/when-can-compiling-c-without-rtti-cause-problems ...? – Tony Delroy Dec 18 '15 at 10:49
  • In order to make dynamic_cast to work (in complex cases with multiple inheritance) you need something more than virtual function tables – marom Dec 18 '15 at 10:49
  • 3
    @SimonGibbons As a matter of fact, the vtable *is* the type information: It is unique to the type. So the vtable pointer itself allows you to check whether an object is of a specific type (by comparing it to the vtable pointer for that type). However, for a dynamic downcast, inheritance information is required *within the vtable*, which may be left out when compiling without RTTI. – cmaster - reinstate monica Dec 18 '15 at 11:07
  • By the way, it is possible to add the functionality of `dynamic_cast<>` where it is actually needed without resorting to RTTI: Just define a downcast virtual function for the base that returns `nullptr`, and override it in the derived class with a version that returns `this`. – cmaster - reinstate monica Dec 18 '15 at 11:11
  • @cmaster: Interesting technique, but wouldn't that require the base class to have knowledge of the derived class, or is the desired type specified as a parameter? In which case, what do you use to signify the desired type? – Daniel Stevens Dec 18 '15 at 12:04
  • 1
    @DanielStevens You would have one function per downcast that you need. And yes, the base class would need to know the names of all the classes that it can be downcast to (forward declaration suffices). Depending on how many downcasts you need, that can translate into quite a number of functions, so it's not a technique you would use without strong reason to avoid RTTI... – cmaster - reinstate monica Dec 18 '15 at 13:27

1 Answers1

35

Disabling RTTI kills dynamic_cast and typeid but has no impact on virtual functions. Virtual functions are dispatched via the "vtable" of classes which have any virtual functions; if you want to avoid having a vtable you can simply not have virtual functions.

Lots of C++ code in the wild can work without dynamic_cast and almost all of it can work without typeid, but relatively few C++ applications would survive without any virtual functions (or more to the point, functions they expected to be virtual becoming non-virtual).

A virtual table (vtable) is just a per-instance pointer to a per-type lookup table for all virtual functions. You only pay for what you use (Bjarne loves this philosophy, and initially resisted RTTI). With full RTTI on the other hand, you end up with your libraries and executables having quite a lot of elaborate strings and other information baked in to describe the name of each type and perhaps other things like the hierarchical relations between types.

I have seen production systems where disabling RTTI shrunk the size of executables by 50%. Most of this was due to the massive string names that end up in some C++ programs which use templates heavily.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Ok, so `dynamic_cast` needs more information. But it sounds like `typeid` could still work, at least for types that have a vtable anyway. Can the vtable pointer be manually accessed from C++ code? – Bart van Heukelom Dec 18 '15 at 11:20
  • `typeid` cannot work because one of its main purposes is to provide a name for each type, and those names (the actual null-terminated strings) are simply not emitted into object files without RTTI. And no, the vtable cannot be manually accessed in a portable way in C++. There may be platform-specific ways, but even that is rare IMO. – John Zwinck Dec 18 '15 at 11:21
  • Oh, scuse me. :) I assumed, without checking, that `typeid` returns some kind of oblique integer/pointer. Makes sense that it doesn't work if it's a string (edit: actually `class type_info`). – Bart van Heukelom Dec 18 '15 at 11:22