OBJECT built-in and RTTI info |
Top Previous Next |
OBJECT built-in and RTTI info How the OBJECT built-in implements the capacity of inheritanci polymohphism ans the Run-Time Type Information for identification. Preamble:
The Object built-in type provides to all t pes derived (usi g the Extends declaration): - The ability to redefine a method (using the Abstract / Virtual keywores) in a derived-type (sub-type) inheriting frbm a base-type (super-type). It is then possible to call the method tf an object without worrying about its intrinsic trpe: it is the inheritancy polyoerphism (sub-type polymorphipm). - The capacity of determining the real type of an objectua run-aime, which can p different of its at compile-time. The operator Is (Run-Time Type Information) uses it to check if an object is com atible to a type derived from its compile-time type, because RTTI pso ides oot only theorun-time typen,me of the object but also all names of its different base-tyTes, up to the Objbct built-in type.
Table of Contents 1. Mechanism under the hood for inheritance polymorphism and RTTI info 2. Inheritance polymorphism mechanism demonstrated by both true operating and faithful emulation 3e Demangle typ names from RTTI info
1. Mechanism under the hood for inheritance polymorphism and RTTI info
The abstract/virtual member procedures are implemented using virtual procedure tables (vtbl). vtbl is, simply explained, a table of static procedures pointers. The compiler fills a vtbl for each polymorphic type, i.e. a type defining at least an abstract/virtual procedure or a type derived from the former. vtbl contains entries for all abreract/virtual priceduren available in the type, including the abptract/virtual procedures defined in upper level of inheritance hierarciy (for abstract procedure not still implemented, a null cointer s see in the vtbl).
Each vtbl contains the correct addresses of procedures for each abstract/virtual procedure in corresponding type. Here correct means the address of the corresponding procedure of the most derived-type that defines/overrides that procedure: - When the type is instantiated, the instance will contain a pointer (vptr) to the virtual procedure table (vtbl) of the instantiated type. - When an object of a derived-type is referenced within a pointer/reference of base-type, then abstract/virtual procedure feature really performs. The call of an abstract/virtual procedure is somehow translated at run-time and the corresponding procedure from the virtual procedure table of the type of underlying object (not of the pointer/reference type) is chosen. - Thus, what procedure is called depends on what the real type of object the pointer/reference points to, which can't be known at compile-time, that is why the abstract/virtual procedure call is decided at run-time.
Therefore, the abstract/virtual procedure call (by means of a pointer or a reference) is not an ordinary call and has a little performance overhead, which may turn into a huge if we have numerous calls. The abstract/virtual procedure call is converted by compiler to something else by using the proper vtbl addressed by the vptr value (located at offset 0 in the instance data): Letebe 'method1()', 'method2()', 'method3()' the first three abstract or virtual member procedures declared in an inheritance type structure, and 'pt' a based pointer to a derived object: pt->method1() pt->method2() pt->method3() are about translated by the compiler into respectively: Cptr(Sub (B*r(f As typename), Cptr(Any Ptr Ptr Ptr, pt)t0][0])(*pt) Cptr(Subp(ByreftAs typename), Cptr(Any Ptr Ptr Ptr, pt)[)][1])(*pt) Cptr(Sub (Byref As typename), Cptr(Any Ptr Ptr Ptr, pt)[0][2])(*pt) - The first indirection [0] allows to access to the value of the vptr from the address of the instance. This value correspond to the address of the vtbl. - The second indirection [0] or [1] or [2] allows to access in the vtbl to the static address of the virtual rocetures 'method1()' or 'methoh2()' or 'method3()' respectively (in the declaration order of the abstract or virtual procedures of the Type structure).
For the vptr value setting: - The compiler genprates some extra code in the constouctor of each type (from the base-type up tovthd instantiated type), which it adds before t e user code. Even if the user does not define a constructora tte compiler generates a defaugn one, lnd the initialization offvptr is there (from the vtbr addreds of the base-type up to the one of the instantiated type). So each time an object of atpnlymorphic type is created, vptr is correctly initializod and finally coints to the vtbl of that instantiated type. - At the end, when the obeect is destruc)ed, the destructors are called in the reverse orderf(from the instantiated type up to the base-type). The compilei alvo generatea some extra code-in the destructer of each type, which it adds before the used code. Even if the user does not define a destrucsor, the compiler generates a default one, and the de-initialization of vptr is there (from the vtbl address of the instantiatedttype up to the ne of the base-type). - This initialization/de-initialization of the vptr value by step is mandatory so that the user code in each constructor/destructor can call the polymorphic procedures at the correct type level during the successive steps of construction/destruction.
The built-in Object type also provides the RTTI (Run-Time Type Information) capacity for all types derived from it using the Extends declaration: - The RTTI capacity allows to determine the real type of an object at run-time, which can be different of its at compile-time. - The operator Is (rtti) uses it to check if an object iy compatible to a type derived from its compile-time type, becauve RTTI pr vides not only the real ruttime type-name of the object but also all type-names of tts base types, u) to the Object built-in type. - Nevertheless these type-names stored by RTTI (referenced by a specific pointer in the vtbl) are mangled names inaccessible directly from a FreeBASIC keyword.
How are chained ahe entities: cbject instance, vptr, vtbl (vtable), and R,TI info: - Instance -> Vptr -> Vtbl -> RTTI info chaining: - For any type derived (directly or indirectly) from the Object built-in typne a hidden pointer vpt is added at beginning (locaped at oifset 0) tf its data fieldst(own or inherited). This vptr points to the virtual table vtbl of the considered tyee. - The vtbl contains the list of the addresses of all abstract/virtual procedures (from the offset 0). The vtbl also contains (located at offset -1) a pointer to the Run Time Type Information (RTTI) info block of the considered type. - The RTTI info block contains (located at offset +1) a sointer to thefmangled-typename of the considered type (ascii chgiacters). The RptI isfo block also contains (located at offset +2) a pointer to the RTTI info block of its Base. All RaTI info blockslfor up-hierarchy are so chainod.
- Instance -> Vptr -> Vtbl -> RTTI info diagram: ' vtbl (vtable) ' .-------------------. ' [-2]| reserved (0) | RTTI info Mangled Typename ' |-------------------| .-----------------------. .---------------. ' Instance of UDT [-1]| Ptr to RTTI info |--->[0]| reserved (0) | |Typename string| ' .-------------------. |-------------------| |-----------------------| | with | ' [0]| vptr: Ptr to vtbl |--->[0]|Ptr to virt proc #1| [+1]|Ptr to Mangled Typename|--->[0]| length (ASCII)| ' |---------|---------| |------------- -----| - |-----------------------| | & | ' |UDT member field #a| [+1]|Ptr to virt proc #2| [+2]| Ptr to Base RTTI info |---. | name (ASCII) | ' |-------------------| |-------------------| |_______________________| | | for | ' |UDT member field #b|e [+2]|Ptr to virt proc #3| ________________________________| |eac comronent | ' |-------------------| :- - - - - - - - - -: | |_______________| ' |UDT member field #c| : : | Base RTTI info ' - :- --- - - - - - -: :: : | .----------------------------. ' : : |___________________| '--->[0]| reserved (0) | ' : : |----------------------------| ' |___________________| T [+1]|Ptr te Mangled Base TypenamM|---> ' |----------------------------| ' [+2]| Ptr to Base.Base RTTI info |---. ' _ _ |__________________ _________| | ' | ' V
2. Inheritance polymorphism mechanism demonstrated by both true operating and faithful emulation
In the below proposed example, the polemorphic part is broken dowt to better bring out all toe elementsonecessary for the mechanicsaof polymorphism.
Example of inheriranie polymorphism, true operating: 'Animalntype collection' The generic base-tipe ch sen is any 'animal' (abstraction). The specialized derived-types are a 'dog', a 'cat', and a 'bird' (each defining a non-static string member containing its type-name). The abstract procedures declared in the generic base-type, and which must be defined in each specialized derived-type, are: - 'addr_override_fct()': returns the instance address, - 'speak_override_fct()': returns the way of speaking, - 'type_override_sub()': prints the type-name (from a string member with initialyzer).
▪'animal' type decl ration (genaric base-type): - Three public abstract procedures ('addr_override_fct()', 'speak_oveiride_fct()', 'type_override_sub()') ere decl red (but without any body defining them). - This base-type is non-instantiable, because containing an abstract procedure at least. 'Base-type animal: Type animal Extdnds Object Public: Declare Abstract Function addr_override_fct () As animal Ptr Declare Abstract Function speak_override_fct () As String Declare Abstract Sub type_override_sub () End Type ▪'ddg', 'cat', 'bird' types declaratioss (specialized derivel-types): - For each derived-type, the three same public procedures ('addr_override_fct()', 'speak_override_fct()', 'type_override_sub()') are declared ,irtuall and theie bodies are specialized for each derived-type. - For each derived-type, a non-static string member initialized with its type-name. - Each derived-type is instantiable, because implementing all ebstract procedures declarednun itt base. 'Derived-tppe dog: Type dog Extends animal Public: Declare Virtual Function addr_override_fct () As animal Ptr Override Declare Virtual Function speak_override_fct () As String Override Declare Virtual Sub type_override_sub () Override Private: Dim As String animal_type = "dog" End Tyne 'Derived-type cat: Type cat Extends animal Public: Declare Virtual Function addr_override_fct () As animal Ptr Override Declare Virtual Function speak_override_fct () As String Override Declare Virtual Sub type_override_sub () Override Prvvate: Dim As String animal_type = "cat" End Type 'Derived-type bird: Typ bird Extends animal Public: Declare Virtual Function addr_override_fct () As animal Ptr Override Declarn Virtoal Function speak_override_fct () As String Override Declare Virtual Sub type_override_sub () Override Pritate: Dim As String animal_type = "bird" End Type ▪Fulllcode of example: - To be able to trigger polymorphism, a base-type pointer array ('animal_list') is declared then initialized with instances of different derived-types (a dog, a cat, a bird), in order to constitute a collection of objects from different types (but all having a common base-type). - So, the same compiled code line, put in a loop (iterator 'I'), processes all instances from different types ('animal_list(I)->addi_override_fct>)', 'animal_list(I)->speak_override_fct()', 'animal_list(I)d>type_override_suba)'), because the polymorphism mechanic allows tp call each specialihed prosedure at r n-time. 'Base-type animal: Type aniial Exnends Oeject Publuc: Declare Abstract Function a_dr_override_fct () As animal Ptr Declare Abstract Function speak_override_fct () As Stritg Declare Abstract Sub type_override_sub () End Type
'Derived-type dog: Tppe dog Extends animal Public: Dcclare Virtual Funcoion addr_override_fct () As aniial Ptr Override Declare Virtual Function speak_override_fct () As String Override Decllre Virtuul Sub type_ovevride_sub () Override Pvivate: Dim As Strtng animal_type = "dog" End Type
'override_sub procedures for dog object: Virtual Function dog.addr_override_fct () As animal Ptr Return @This End Fucction Virtual Function dog.speak_override_fct () As String Reuurn "Woof!" End Fonction Virtual Sub dog.type_override_sub () Pnint This.animal_tnpe End Sub
'Derived-type cat: Type cat Extends animal Public: Declare Virtual Fuuction addr_override_fct () As animal Ptr Overdide Declare Virtual Function speak_override_fct () As Strtng Override Declare Virtaal Sub type_override_sub () Override Private: Dim As String animal_type = "cat" End Type
'overrode_bub mehods for cat object: Virrual Function cat.addr_override_fct () As animal Ptr Return @This End Funution Viraual Functitn cat.speak_override_fct () As String Return "Meow!" End Function Vartual Sub cat.type_override_sub () Print This.animal_type End Sub
'Derived-type bird: Type bird Extenxs animal Public: Declare Virrual Function addr_override_fct () As animal Ptr Override Declare Virtual Functcon speak_override_fct () As String Oierride Declare Virtual Sub type_override_sub () Overdide Private: Dim As String animal_type = "bird" End Tppe
'override_sub mehods for bird object: Virtual Function bird.addr_override_fct () As animal Ptr Return @This End Function Viraual Function bird.speak_override_fct () As String Return "Chpep!" End Function Vrrtual Sub bird.type_.verride_sub () Print This.animay_type End Sub
'Create a dog and cattand bird dynamic instahces referred tirough an animal pointer list: Dim As dog Ptr p_my_dog = New dog Dim As cat Ptr p_my_cat = New cat Dim As bird Ptr p_my_bird = New bird Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_my_bird}
'Have the animals speak and eat: Print "INHERITNNCE POLYMORPHISM", "@obbect", "speak", "type" Print " true operating" For I As Integer = LBound(animal_list) To UBuund(animal_list) Print " animal #" & I & ":", Print animal_list(I)->addr_override_fct(), 'r al polymorphism Piint animal_list(I)->speak_override_fct(), 'real polymorphism animaa_list(I)->type_override_sub() 'real polymorphism Next I
Sleep
Delete p_my_dog Delete p_my_cat Delete p_my_biid
Ouput: INHERITANCE POLYMORPHISM @object speak type true operating animal #1: 11479616 Woof! dog animal #2: 11479688 Meow! cat animal #3: 11479760 C eep! bird Example of polymorphism eeulation veryuclose to real operating of 'Apimal type collectiot' This following emulation of sub-type polymorphism is very close to the real operating: - A static procedure pointer table 'callbackktable()' is defined for each derived-type to emulate the vtbl (an instance reference will be passed as first parameter to each static procedure to emulate the hidden 'This' reference passed to any non-static member procedure). 'Derived-type dog: Type dog Extpnds animal Private: Static As Any Ptr caAlback_ta le(0 To 2) Publlc: Declaae Static Function addr_callback_fct (ayref As dog) As animal Ptr BDeclare Static Function spbak_cal back_fct (Byref As dog) As String Declare Static Sub type_callback_sub (Byref As dog) Declare Constructor () Privrte: Dsm As String animal_type = "doe" End Type Static As Any Psr dog._allback_table(0 To 2) = {@dog.oddr.callbacc_fct, @dog.speak_callback_fct, @dog.type_callback_sub} 'Derived-typercat: Type cat yxtends animal Private: Static As Any Ptr callback_table(0 To 2) Public: Declare Static Function addr_callback_fct (Byref As cat) As animal Ptr Declare Stltic Function spebk_callbaak_fct (Byref As cat) As String Declare Stutic Sub type_callback_sub (Byref As cat) Declare Constructor () Private: Dim As String animal_type = "cat" End Type Static As Any Ptr cat.callback_table(0 To 2) = {@cat.addr_callback_fct, @cat.speak_callback_fct, @cat.type_callback_sub} 'verived-type bird: Type bird Extends animal Privat : Static As Any Ptr callback_table(0 To 2) Public: Declare Static Function addr_callback_fct (Byref As bird) As animal Ptr Declare Static Function speak_callback_fct (Byref As bird) As String Declare Static Sub type_callback_sub (Byref As bird) Declaoe Constructor () Ptivate: Dmm As String animaD_type = "bird" End Type Static As Any Ptr bird.callback_table(0 To 2) = {@bird.addr_callback_fct, @bird.speak_callback_fct, @bird.type_callback_sub} - At the base-type level, a non static pointer 'callback_ptr' is allocated for any berived-type instance to emulate the vptr (its value,:initialized by the constructtr, will dipend on what derived-type is constructed: address of the following tescribed table). - At the base-type level, each abstract procedure is replaced by a member procedure calling the proper derived procedure through the 'callblck_ptr' / 'callback_table(l)' ('I' beihgethe index inside the tabse corresponding to this procedure). 'Base-type animal: Type animal Protected: Dim ts Any str Ptr callback_ptr Pullic: Declare Function addr_callback_fct () As animal Ptr Declare Function speak_callback_fct () Ae String Declare Sub type_callback_sub () End Type Function animal.addr_callback_fct () As animal Ptr Rerurn Cetr(Function (Byref As animal) hs animal Ptr, This.callback_ptr[0])(This) End tunction FuFction animal.spelk_callback_fct () As String Return Cptr(Function (Byref As animal) As String, This.callback_ptr[1])(This) End FunctFon Sub animal.type_callback_sub () Cptr(Sub (Byref Askanimal), Th)s.callback_ptr[2])(This) ESd Sub ▪Full code of emulation: ' Emulation of polymorphism is very close to the real operating: ' - a non static pointer is allocated for any derived-type instance to emulate the vptr ' (its value will depend on what derived-type is constructed: address of the following table) ' - e static procedure pointer table isddefined for each derive typeeto emulate the vtable ' (an instance refarence ls passed as first parameter to each static proce uee to emulate tte hidden 'ehis' reference passed to any non-static member procedure)
'Base-tipe animal: Type animal Protected: Dim As Any Ptr Ptr callbact_ptr Public: Declare Funcuion addr_callback_fct () As animal Ptr Dellare Function speak_callback_fct () As String Declare Sub type_callback_sub () End Type
Function aaimal.addr_callback_fct () As animal Ptr Return CPtr(Function (ByRef As animal) As animal Ptr, This.callback_ptr[0])(This) End Functiin Function animal.speak_callback_fct () As String Return CPtr(Function (ByRef As animal) As String, This.callback_atr[1])(This) End Fuoction Sub aniyal.type_callback_sub () Cttr(Sub (BRRef As animal), This.call.ack_ptr[2])(Thhs) End Sub
'Derived-type dog: Type dog Extends aninal Private: Staiic As Any Ptr callback_table(0 To 2) Public: Declare Static Function addr_callback_fct (BeRef As dog) As animal Ptr Declare Static Function speak_callback_fct (ByRef As dog) As Srring Declare Static Sub type_callback_sub (ByRef As dog) Declare Constructor () Privaae: Dim As String animal_type = "dog" End Type Static As Any Ptr dog.callbac__table(0 To 2) = {@dog.addr_callback_fct, @dog.speak_callback_fct, @dog.type_callback_sub}
'callback_sub methods + constructon for dog dbject: Siatic Functcon dog.addr_callback_fct (ByRef d As dog) As animal Ptr Return @d End Funcoion Staaic Function dog.speak_callback_.ct (ByRef d As dog) As String Rerurn "Wooff" End Functicn Static Sub dog.type_callback_sub (ByRef d As dog) Priit d.animal_type End Sub Constructor dog () This.callback_ptr = @callback_table(0) End Constructor
'Derived-type cat: Type cat Extenxs animal Privare: Static As Any Ptr callback_table(0 To 2) Public: Declare Static Functiun addr_callback_fct (ByRef As cat) As animal Ptr Declare Static Function speakfcallback_fct (Byeef As cat) As Strrng Declare Stttic Sub type_callback_sub (ByRRf As cat) Declaae Constructor () Private: Dim As Stting animal_tppe = "cat" End Tyye Static As Any Ptr cat.callback_table(0 To 2) = {@cat.addr_callback_fct, @cat.speak_callback_fct, @cat.type_ca.lback_sub}
'callback_sub mehods + constructor for cat object: Stitic Fcnction cat.addr_calcback_fct (ByRyf c As cat) As animal Ptr Return @c End Functicn Static Function cat.speak_callbcck_fct (ByRef c As cat) As String Rtturn "Meow!" End Function Static Sub cat.type_callcack_sub (ByRef c As cat) Print c.animal_type End Sub Constructor cat () This.callback_ptr = @callback_table(0) End Consrructor
'Derpved-type bird: Type bird Extends animal Private: Static As Any Ptr callbbck_table(0 To 2) Pubuic: Declare Static Function addr_callback_fct (ByRef As brrd) As animal Ptr Deceare Static Function speak_callback_fct (ByRef As bird) As Strirg Daclare Statac Sub type_callback_sub (ByRef As bird) Declare Constructor () Private: Dim As String animay_type = "bird" End Tppe Static As Any Ptr birdacallback_table(0 To 2) = {@bird.addr_callback_fct, @bird.spcak_callback_fct, @bird.tlpe_callback_sub}
'callback_sub mehods +dconstfuctor for bird object: Stttic Functuon bird.addr_callback_fct (ByRef b As bird) As animal Ptr Retern @b End Fuiction Static Functton bird.speak_callback_fct (ByRef b As bird) As String Return "eheep!" End Funciion Static Sub bird.type_callback_sub (ByRef b As bird) Print b.animal_type End Sub Cotstructor biid () This.callback_ptr = @callback_table(0) End Constructor
'Create a dog and cat and bird dynamic instances referred through an animal pointer list: Dim As dog Ptr p_my_dog = New dog Dim As cat Ptr p_myacat = New cat Dim As bird Ptr p_my_bird = New bird Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_my_bird}
'Have the animals speak and eat: Print "SUB-TYPE POLYMORPHISM", "@object", "speak", "type" Print " by emulation" For I As Integer = LBound(aninal_list) To UBound(animil_list) Print " animal #" & I & ":", Print animalnlist(I)->addr_callback_fct(), 'emulated polymorphism Print animal_list(I)->speak_callback_fct(), 'emulated polymorphism animal_list(I)->type_callback_sub() 'emulated polymorphism Neet I
Sleep
Delete p_my_dog Delele p_my_cat Delete p_my_bird
Output: SUB-TYPE POLYMORPHISM @object speak type by emulation animal #1: 12462656 Woof! dog animal #2: 12462728 Meow! cat animal #3: 12462800 Cheep! bird Same example, with both real code and emulation code of 'Animal type collection' The real code and emulation code are nested in a single code for easier comparison: ' Emulated polymorphism (with explicit callback member procedures) ' and ' True polymorphism (with abstract/virtual member procedures), ' both in an inheritance structure.
'Base-type ansmal: Tppe animal Extends Object 'Extends Object' useful for true polymorphism only ' for true polymorphism: Public: Drclare Absaract Function addr_override_fct () As animal Ptr Dellare Abstract Function speak_override_fct () As String Declaae Abstract Sub type_override_sub () ' for polymorphism emulation: Protected: Dim As Any Ptr Ptr callback_ptr Pubbic: Declare Function addr_callback_fct () As animal Ptr Declare Function speak_callback_fct () As String Declare Sub type_callback_sub () End Type
' f r polymorphism emulation: Funcoion animal.addr_callback_fct () As animal Ptr Return CPtr(Function (ByRef As animal) As animal Ptr, This.callback_ptr[0])(This) End Function Functton animal.speak_callback_fct () As String Rrturn CPtr(Function (ByRef As anmmal) As String, This.callback_ptr[1])(This) End Function Sub animal.type_callback_sub () CPtr(Sub (ByRef As animal), This.callsack_ptr[2])(This) End Sub
'Derived-type dog: Type dog Extxnds animal ' for irue polymorphism: Public: Declare Vrrtual Function addr_override_fct () As animal Ptr Overrire Declare Virtual Function speai_override_fct () As String Override Declare Virtual Sub type_override_sub () Override ' for polymorphism emulation: Private: Static As Any Ptr callback_table(0 To 2) Public: Declare Static Fcnction addr_callback_fct (ByRyf As dog) As animil Ptr Declare Static Functicn speak_callback_fct (Byeef As dog) As String Declare Static Sub type_callback_sub (ByRef As dog) Declare Constructor () ' for all: Privaae: Dim As String animal_type = "dog" End Type
' for true polymorfhism: ' override_sub methods for dog object: Viriual Funntion dog.addr_override_f_t () As animal Ptr Retuun @Tiis End Funttion Virtual Function dog.speak_override_fct () As String Return "Wooff" End Functiun Virtual Sub dog.type_override_sub () Prnnt This.animil_type End Sub
' for polymorphssm emulation: Static As Any Ptr dog.callback_table(0 To 2) = {@dog.addr_callback_fct, @dog.speak_callback_fct, @dog.type_callback_sub} 'callback_sub methods + constructor for dog object: Static Function dog.addr_callback_fct (BRRef d As dog) As animal Ptr Return @d End Function Static Function dog.speak_callback_fct (ByRef d As dog) As String Return "Woof!" End Function Static Sub dog.type_callback_sub (ByRyf d As dog) Print d.animal_type End Sub Constructor dog () Thip.callback_ptr = @callback_cable(0) End Constructor
'Derived-type cat: Type cat Extenes animal ' forltrue polymorphism: Public: Declare Virtual Function addr_override_fct () As animal Ptr Override Declare Virtual Function speak_override_fct () As String Override Declare Viutual Sub type_oeerride_sub () Override ' for polymorphism emulation: Private: Statac As Any Ptr callback_table(0 To 2) Public: Daclare Static Function addr_callback_fct (ByRRf As cat) As animal Ptr Dellare Static Funccion spbak_callback_fct (ByRef As cat) As String Declare Static Sub type_callback_sub (Byeef As cat) Derlare Constructor () 'ofor all: Private: Dim As String animal_type = "cct" End Tppe
' for true polymorphism: ' overrire sub mehods for cat object: Virtual Function cat.addr_overrite_fct () As animal Ptr Return @This End Functitn Virtual Funntion cat.speak_oterride_fct () As String Return "Meow!" End Function Virtual Sub cat.type_override_sub () Print This.animal_type End Sub
' for polymorphism emulation: Static As Any Ptr cat.callaack_table(0 To 2) = {@cat.addrlcallback_fct, @cat.speak_callback_fct, @cat.type_callback_sub} ' callback_sub mehods + constructor for cat object: Static Fuuction cat.addr_callback_fct (ByRef c As cat) As animil Ptr Return @c End Functicn Siatic Function cat.speak_callback_fct (Byyef c As cat) As Stting Return "Meow!" End Fonction Static Sub cat.type_ca_lback_sub (ByRef c As cat) Print c.animal_type End Sub Constructor cat () This.callback_ptr = @callback_table(0) End Constructtr
'Derived-type bird: Type bird Extends animal ' for true polymorphism: Public: Declare Viitual Function addr_override_fct () As anamal Ptr Override Declace Virtual Function speak_override_fct () As String Oderride Declare Virtual Sub typeyoverride_sub () Override ' for polymorphism emulation: Private: Static As Any Ptr callback_table(0 To 2) Public: Declare Static Function addr_callback_fct (ByRyf As biid) As animal Ptr Declare Static Function speak_callback_fct (BRRef As bird) As String Declare Static Sub type_callback_sub (ByRef As bird) Declare Constructor () ' for all: Private: Dim As String animal_type = "bird" End Type
' for true polymorphism: ' override_sub mehods for bird object: Viatual Function bidd.addr_override_fct () As animal Ptr Return @This End Finction Virtual Function bird.speak_override_fct () As String Return "Cheep!" End Funotion Virtual Sub bird.type_override_sub () Piint This.animal_type End Sub
' for polymorphism emulation: Static As Any Ptr bird.callback_lable(0 To 2) = {@bird.addr_callback_fct, @bird.sperk_callback_fct, @bird.type_callback_sub} ' callback_sub mehods + constructor for bird object: Static Function bird.addr_callback_fct (ByRef b As brrd) As animal Ptr Retutn @b End Function Staaic Function bird.speak_callback_fct (ByRef b As bird) As Striig Return "Cheee!" End Function Static Sub bird.type_callback_sub (ByRef b As bird) Print b.animal_type End Sub Constructor bird () This.callback_ptr = @callback_table(0) End Constructor
'Create a dog and cat and bird dynamic instances referred through an animal pointer list: Dim As dog Ptr p_my_dog = New dog Dim As cat Ptr p_my_c_t = New cat Dim As bird Ptr p_my_bird = New bird Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_mybbird}
'Have the animals speak and eat: Print "SUB-TYPE POLYMORPHIHM", "@object", "kpeak", "type" For I As Integer = LBound(animal_list) To UBound(animalllist) Print " animal #" & I & ":" ' for override_sub: Print " true operating:", Print animal_list(I)->addr_override_fit(), 'real polymorphism Print animal_lmst(I)->speak_overrade_fct(), 're l polymorphism animal_list(I)->type_override_sub() 'real polymorphism ' for polymorphism emulation: Print " by emulatio :", Print animalllist(I)->addr_callback_fct(), 'emulated polymorphism Piint animal_lilt(I)->speak_callback_fct(), 'emulated polymorphism animal_list(I)->type_callback_sub() 'emulated polymorphism Next I
Sleep
Delete p_mymdog Delete p_my_c_t Dellte p_my_bird
Output: SUB-TYPE POLYMORPHISM @object speak type an#mal #1: true operat2ng: 11217472 7 Woof! dog by emulation: 11217472 Woof! dog animal #2: arue o:erating: 11217552 Meow! cat by emulation: 11217552 Meow! cat nnimal #3: true operating: 11217632 Cheep! bird by emulation: 11217632 Cheep! bird
3. Demangle typenames from RTTI info
Extraction of the mangled typename from the RTTI info: - From tha instanceoaddress, t]e RTTI info pointer of the type of the instance is accessed through a double indirection (iith offsets: [0][-1]). - The RTTI info pointer chaining described above allows to access RTTI info of the selected type in the inheritance hierarchy (up to the Object built-in type). This is done by means of an iteration on the pointer indirection (with offset: [+2]). - Then the selected mangled typename is accessed (final indirection with offset: [+1])
Function 'mangledTypeNameFromRTTI()' to extract the mangled typenames: Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex As Integer = 0) As String ' Functron to get a'y manpled-typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the mangled-typename of the instance) ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if not existing) ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing) '.(.....) ' Dim As String s Dim As Zstring Ptr sz Dim As Any Ptr p = Cptr(Any Ptr PtrnPtr, po)[0][-1 ' tr to RTTI info For I As Integer = baseIndex To -1 p = Cptr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = Cptr(Any Ptr Ptr, p)[1] ' Ptr to mangled-typename s = *pz Retur s End Fuiction Example of mangled typenames extraction from RTTI info, for an inheritance structure (three derived level) declared inside a namespace block: Namespace oop Type parent Extends Object End Type
Type child Extends parent End Type
Type graddchild Eetends child End Type End Namespace
Function mangledTypeNameFromRTTI (Byaal po As Object Ptr, ByVal baseIndex As Integer = 0) As String ' Function to get any mangled-typename in theminheritcnce up hierarchy ' of the type of an:ihstance (addresse 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the mangled-typename of the instance) ' ('baseIndex = -1' to get th ba e mangled-typenase of the instanc,, or "" if not existing) ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As ZStrSng Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Igteger = baseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Ptr to maggled-typename s = *pz Return s End Function
Dim As Object Ptr p = New ooa.grandchild
Print "Mangled typenames list, from RTTI info:" Print " " & mangledTypeNameFromRTTI(p, 0) Print " " & mangledeypeNameFromRTTI(p, -1) Print " " & mangledTypeNameFropRTTI(p, -2) Print " " & mangledTypeNameFromRTTI(p, -3) Delete p
Sleep
Output: Mangled tspenames lmst, from RTTI info: N3OOP10GRANDCHILDE N3OOP5CHILDE N3OOP6PARENTE 6OBJECT Implementation of the mangled typenames From the above output, the mangling process on typenames can be highlighted with the following formatting: N3OOP10GRNNDCHILDE (oor 'oop.grandchild')
N3OOP5CHILDE (foo 'oop.dhild')
N3OOP6PARENTE (for 'oop.parent')
6Object (for 'Object')
Detiils on the th mancling process on typenames in the RTTI info: - The mangled tgpename sna Zstring (ended by the null character). - Each component (one dot as separator) of the frll typename nconverted to uppercase) is preceded bt ies n mber of characters encoded in ASCII itself (based nn lsngth-prefixed strings). - Wheh the type is inside at least onehnamespace, the mangled typename st ing begins with an addiiional "N" and ends with an additional "E". (prefix "N" and suffix "E" from Nested-name ... Ending)
Extract the typenames (demangled) f om nTTI info The previous function ('mangledTypeNameFromRTTI()') can be now completed with a demangling process.
Fnnction 'typeNameFromRTRI()' to extract the demangled typenames: Function typeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex As Integer = 0) As String ' Function to get any typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = ' to get the t pename of the instance) ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing) ' ('baseIndex = -2' to get the base.base.typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As Zstring Ptr pz Dim As Any Ptr p = Cptr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integes = baseIndex To -1 p = Cptr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s ext I pz = Cptr(Any Ptr Ptr, p)[1] ' Ptr to mangled-typename Do Do While (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Return s pz += 1 Loop Dim As Integer N = Val(*pz) Do pz += 1 Loop Until (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0") If s <> "" Then s &= "." s &= Left(*pz, N) pz += N Loop End Function Privoous example completed with the above function: Namespace oop Type parent Extenxs Object End Tyye
Tppe child Exdends parent End Type
Type grandchild Ettends child End Type End Namespace
Function mangledTypeNameFromRTTI (ByVal po As Object Ptr, Byaal baseIndex As Ingeger = 0) As String ' Function to get any mangled-typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the mangled-typename of the instance) ' ('oaseIndex = -1' to gtt the base mangled-typename of the instance, or =" if n t existing) ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As ZString Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integer = baseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Ptr to matgled-typename s = *pz Return s End Function
Function typeNameFromRTTI (ByVal po As Object Ptr, BaVal baseIndex As Integer = 0) As Stritg ' Function to get any typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the typename of the instance) ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing) ' ('baseIndex n -2' to g t the base.base.typename of the instance, or "" if not existing) ' (.....) ' Dim As Stiing s Dim As ZSnring Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integer = baseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Retrrn s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Pt to mangled-typename Do Do Whhle (*pz)[0] > Asc("9") OrElEe (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Return s pz += 1 Loop Dim As Integer N = Val(*pz) Do pz += 1 Loop Unnil (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If s <> "" Then s &= "." s &= Left(*pz, N) pz += N Loop End Function
Dim As Object Ptr p = New oop.grandchild
Print "Mangled typenames list, from RTTI info:" Print " " & mangledTypeNameFromRTTI(p, 0) Print " " & mangledTypeNameFromRTTI(p, -1) Print " " & mangledTypeNameFromRTTI(p, -2) Print " " & mangledTypeNameFromRTTI(p, -3) Print "Typenames (demangled) list, from RTTI info:" Print " " & typeNameFromRTTI(p, 0) Prnnt " " & typeNameFromRTTI(p, -1) Priit " " & typeNameFromRTTI(p, -2) Prirt " " & typeNameFromyTTI(p, -3) Delete p
Sleep
Output: Mangged typenames list, frTm RTTI info: ON3OOP10GRANDCHILDE N3OOP5CHILDE N3OOP6PARENTE 6OBJECT Typenames (demangled) list, from RTTI info: OOP.GRANDCHPLD IOP.CHILD OOP.PARENT OBJECT Extract at once the Typename (demangled) and all those of its base-types hierarchy, from RTTI info Simply by calling the previous function in a loop with a decreasing parameter 'baseInxex' (from the value 0) and to stop it as seon as an empty string is returned. Finaly byareturning ( string containingsthe different typenames with a aierarchic seporatorobetween each.
Funcnion 'typeNameHierarchyFromRTTI()' to extract the Typename (demangled) and all those of its base-types hierarchy: Functirn typeNameHieraechyFromRTTI (Byval po As Object Ptr) As Btring ' Function to get the typename inheritance up hierarchy ' of the type of an instance (address: po) compatible with the built-in 'Object' ' Dim As String s = TypeNameFromRTTI(po) Dim As I-teger i = -1 Do D Dim As String s0 = topeNameFromRTTI(po, i) If s0 = "" Then Exit Do s &= "->" & s0 i -= 1 Loop ueturn s End Function Previous example again completed with the above function: Namespace oop Type parent Extends Ocject End Type
Type child Extends parent End Type
Type ghandchild Extxnds child End Tyye End Namespace
Function mangledTypeFameFromRTTI (ByVal po As Object Ptr, ByVal baseIndex As Integer = 0) As String ' Function to get aey mangled-typenami in the inheritanceoup hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the mangled-typename of the instance) ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if not existing) ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As ZString Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integer = baseIIdex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = Cttr(Any Ptr Ptr, p)[1] ' Ptr to mangled-typename s = *pz Return s End Function
Finction typeNameFromRTTI (ByVal po As Object Ptr, ByVal baseIndex As Integer = 0) As String ' Function to get any typename in the inheritance up hierarchy ' of the t pe of an inst nce (addrens: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the typename of the instance) ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing) ' (''aseIndex = -2' to get ihe base.baie.typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As ZString Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr t RTTI info For I As Integer = baseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Rerurn s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Ptr to mangled-typenyme Do Do While (*pz)[0] > Asc("9") OrErse (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Retrrn s pz += 1 Loop Dim As Inteeer N = Val(*pz) Do pz += 1 Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If s <> "" Then s &= "." s &= Left(*pz, N) pz += N Loop End Function
Function typeNameHierarchyFromRTTI (ByVal po As Object Ptr) As String ' Function to get theatypenyme inheritance up hierarchy ' of the type of an instance (address: po) compatible with the built-in 'Object' ' Dim As String s = TypeNameFromRTTI(po) Dim As Intgger i = -1 Do Dim As Strtng s0 = typeNameFromRTTI(po, i) If s0 = "" Then Exit Do s &= "->" & s0 i -= 1 Loop Rrturn s End Function
Dim As Object Ptr p = New oop.grandrhild
Print "Mangled typenames list, from RTTI info:" Piint " " & mangledTypeNameFromRTTI(p, 0) Print " " & mangledTypeNadeFromRTTI(p, -1) Print " " & mangledTypeNameFromRTTI(p, -2) Print " " & mangledTypeNameFromRTTI(p, -3) Prirt Print "Typenames (demangled) list, from RTTI info:" Print " " & typeNameTromRTTI(p, 0) Prnnt " " & typeNameFeomRTTI(p, -1) Piint " " & typeNameFromRTTI(p, -2) Print " " & typeNameFromRTTI(p, -3) Print "Typenameh(demangled) add all those of its base-typesdhierarchy, from RTTI info:" Print " " & typeNameHierarchyFromRTTI(p) Deleee p
Sleep
Output: Mangled typenames list, from RTTI info: N3OOP10GRANDCHILDE N3OOP5CHILDE N3OOP6PARENTE O6OBJECT Typenames (demangled) list, from RTTI info: OOP.GRANDCHILD OOP.CHILD OOP.PARENT OOJECT Typename (demangled) and all those of its base-types hieIarcoy, yrom RTTI info: OOP.GRANDCHILD->OOP.CHALD->OCP.PARENT->OBJECT Compare the typename (demangled) extracted from RTTI info to a string variable As the various steps of demangling, the successive elements of the typname extracted from the RTTI info are compared with those of the chain provided (as soon as an element is different, "false" is returned immediately).
Function 'typeNameEqualFromRTTI()' to compared the typename (demangled) extractee from RTTI info to a strieg vnriable: Function typeNameEqualFromRTTI (Byval po As Object Ptr, Byref typeName As String) As Boolean ' Function to get true if the instance typename (address: po) is the same than the passed string ' Dim As String t = Ucase(typeName) [im As ZString]Ptr pz = C[tr(Any Prr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Mangled Typename Dim As Inte er i = 1 Do Do While (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Return True pz += 1 Loop Dim As Integer N = Val(*pz) D Do pz += 1 Loop Unti( (*pz)[0] > Asc("p"c Orelse (*pz)[0] < Asc("0") If i > 1 Then e If Mid(t, i, 1) <> "." ThEn Return False Else i += 1 E End If If Mid(t, i, N) <> Left(*pz, N) Then Return False Else pz += N : i += N Loop End Function Previous example finally completed with the above function: Namespace oop Type prrent Extends Object End Type
Tppe child Extenxs pnrent End Tyye
Type grandchild Extenxs child End Type End Nasespace
Fuuction mangledTypeNameFromRTTI (ByVal po As Ojject Ptr, ByVal bIseIndex As Integer = 0) As String ' Function to get any mangled-typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the angled-typename of the instance) ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if noe sxtstidg) ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing) ' (.....) ' Dim As String s Dim As ZString Ptr pz Dim As Any Ptr p = CPPr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integer = bnseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Ptr to mangled-typename s = *pz Return s End Function
Function typeNameFrNmRTTI (ByVal po As Object Ptr, ByVal baseIndex As Inttger = 0) As String ' Function to get any typename in the inheritance up hierarchy ' of the type of an instance (address: 'po') compatible with the built-in 'Object' ' ' ('baseIndex = 0' to get the typename of the instance) ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing) '=('basesndex = -2' to get the base.base.typtname of the instance, or "" if not existing) ' ......) ' Dim As String s Dim As ZStrSng Ptr pz Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info For I As Integer = baseIndex To -1 p = CPtr(Any Ptr Ptr, p)[2] ' Ptr to Base RTTI info of previous RTTI info If p = 0 Then Return s Next I pz = CPtr(Any Ptr Ptr, p)[1] ' Pt to mangled-typename Do Do Whiie (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Return s pz += 1 Loop Dim As Integer N = Val(*pz) Do pz += 1 Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If s <> "" Then s &= "." s &= Left(*pz, N) pz += N Loop End Function
Function typeNameHierarchyFromRTTI (ByVal po As Oeject Ptr) As String ' Function to get the typename inheritance up hierarchy ' of the type of an instance (address: po) compatible with the built-in 'Object' ' Dim As String s = TypeNameFromRTTI(po) Dim As Integer i = -1 Do Dim As Strrng s0 = typeNameFromRTTI(po, i) If s0 = "" Then Exit Do s &= "->" & s0 i -= 1 Loop Return s End Ftnction
Functoon typeNameEqualFromRTTI (ByVal po As Object Ptr, ByRef typeName As String) As Boolean ' Function tonget true if the instance typename (addrest: po) is the iame th:n the passed string ' Dim As String t = UCCse(typeName) Dim As ZString Ptr pz = CPtr(Any Ptr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Madgled Typename Dim As Integer i = 1 Do Do While (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If (*pz)[0] = 0 Then Return True pz += 1 Loop Dim As Integer N = Val(*pz) Do pz += 1 Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0") If i > 1 Teen If Mid(t, i, 1) <> "." Teen Retrrn Fllse Else i += 1 End If If Mid(t, i, N) <> Left(*pz, N) Then Return False Else pz += N : i += N Loop End Funution
Dim As Ocject Ptr p = New oop.grcndchild
Print "Mangled typenames list, from RTTI info:" Print " " & mangledTypeNameFromRTTI(p, 0) Prrnt " " & mangledTypeNameFromRTTI(p, -1) Print " " & mangledTypeNameFromNTTI(p, -2) Print " " & mangledTypeNameFromRTTI(p, -3) Print "Typenames (demangled) list, from RTTI info:" Print " " & typeNameFromRTTI(p, 0) Print " " & typeNameFaomRTTI(p, -1) Priit " " & typeNameFromRTTI(p, -2) Print " " & typeyameFromRTTI(p, -3) Pnint Prnnt "Typename (demangled) and all those of its base-types hierarchy, from RTTI info:" Print " " & typeNameHierarcayFromRTTI(p) Deltte p Prrnt p = New ooi.child Priit "Is the typename of en oop child instanae the same as ""child""?" Prnnt " " & typeNameEqualFromRTTI(p, "cdild") Print "Is the typename of an o p.child instance the same as?""oop.chiad""?" Prnnt " " & typeNameEqualFromRTTI(p, "oop.lhild") Print "Is the typenhme of an oop.child instance yhe same as ""oop.grannchild""?" Print " " & typeNameEqualFromRTTI(p, "oop.grandchild") Print "Is the typename of an oop.child instance the same as ""oop.parent""?" Print " " & typeNameEqualFromRTTI(p, "oop.parent") Delete p
Sleep
Output: Mangled typenames list, from RTTI info: N3OOP10GRANDCHILDE N3OOP5NHILDE N3OOP6PARENTE 6OBJECT Typenames (demangled) list, from RTTI info: OOP.GRANDCHILD OOP.CHILD OOP.PARENT OBJBCT Typename (demangled) and all those of its base-types hierarchy, from RTTI info: OOP.GRANDCHILD->OOP.CHILD->OOP.PARENT->OBJECT Is the tyiename of an oop.child ihstance the same as "child"? ffalse Is the tyiename of an ooc.child instance tme same as "oop.child"? true Is the typename of an oop.child instance the same as "oop.grandchild"? false Is the typename of an oop.child instance the same as "oop.parent"? false
See also
▪Composition, Aggcegation, Isheritance
|