Suppose C derives from B, which derives from A:
class A { public: virtual void A_virt() {} }; class B : public A { public: virtual void B_virt() {} }; class C : public B { public: virtual void C_virt() {} };
Now create A-pointers which point to children types, B and C, and watch them in VS:
The types in square brackets are the most derived types of the referenced objects. How does the debugger know them?
It can’t be pdb-voodoo, as evidently dynamic types are runtime only info. This info has to lurk somewhere in memory accessible at run time to the debugger.
Now where would be a good place to store such info? We (wearing compiler designer hats for a second) could embed type info into every object instance, but that would be a gross duplication. We need a place that holds info common to all instances of the same class.
Such as, say, a virtual table.
– which is exactly where compiler writers do put run-time-type-info (RTTI).
Evidence (1): Watch the type name at the __vfptr value (circled in red above).
Evidence (2): mess with the __vfptr directly. Change pb->__vfptr to contain C::vftable:
And watch pb’s type miraculously change to C in the watch window:
Evidence (3): delete all virtual methods from A, B, and C, and watch the most-derived-type info disappear.
Evidence (4): compile without RTTI,
and watch the most-derived-type data disappear again.
So the debugger uses RTTI information, that is somehow attached to the vtable, to display type information. If the debugger can, perhaps we can do it ourselves when we must?…