Run-time type information
Type information inspection taking place at runtime
- 13 min read
- 4 chapters
Related on Lably
Through Computer programming, Data type and Execution (computing)
In the original C++ design, Bjarne Stroustrup did not include run-time type information, because he thought this mechanism was often misused.
Overview
In C++, RTTI can be used to do safe typecasts using the dynamic_cast<T> operator, and to manipulate type information at runtime using the typeid operator and std::type_info class, which itself stores the runtime information. In Object Pascal, RTTI can be used to perform safe type casts with the as operator, test the class to which an object belongs with the is operator, and manipulate type information at run time with classes contained in the RTTI unit (i.e. classes: TRttiContext, TRttiInstanceType, etc.). In Ada, objects of tagged types also store a type tag, which permits the identification of the type of these object at runtime. The in operator can be used to test, at runtime, if an object is of a specific type and may be safely converted to it.
RTTI is available only for classes that are polymorphic, which means they have at least one virtual method. In practice, this is not a limitation because base classes must have a virtual destructor to allow objects of derived classes to perform proper cleanup if they are deleted from a base pointer.
Some compilers have flags to disable RTTI. Using these flags may reduce the overall size of the application, making them especially useful when targeting systems with a limited amount of memory.
Sign in to keep reading
3 more chapters are free with a Lably account.
C++ typeid operator
The typeid keyword is used to determine the class of an object at runtime. It returns a reference to std::type_info object, which exists until the end of the program. The use of typeid, in a non-polymorphic context, is often preferred over dynamic_cast<T> in situations where just the class information is needed, because typeid is always a constant-time procedure, whereas dynamic_cast may need to traverse the class derivation lattice of its argument at runtime. Some aspects of the returned object are implementation-defined, such as std::type_info::name(), and cannot be relied on across compilers to be consistent.
A std::bad_typeid exception are thrown when the expression for typeid() is the result of applying the unary * operator on a null pointer. Whether an exception is thrown for other null reference arguments is implementation-dependent. In other words, for the exception to be guaranteed, the expression must take the form typeid(*p) where p is any expression resulting in a null pointer.
The typeid operator, if used in a context where std::type_info is not visible, is ill-informed. It is defined in header <typeinfo> (or module std).
C++26 offers increased support for reflective type introspection through the type std::meta::info, but it is done at compile-time.
Example
<span id="mwhg"></span><span class="k" id="mwhw">import</span><span class="w" id="mwiA"> </span><span class="n" id="mwiQ">std</span><span class="p" id="mwig">;</span> <span class="k" id="mwiw">using</span><span class="w" id="mwjA"> </span><span class="n" id="mwjQ">std</span><span class="o" id="mwjg">::</span><span class="n" id="mwjw">bad_typeid</span><span class="p" id="mwkA">;</span> <span class="k" id="mwkQ">using</span><span class="w" id="mwkg"> </span><span class="n" id="mwkw">std</span><span class="o" id="mwlA">::</span><span class="n" id="mwlQ">type_info</span><span class="p" id="mwlg">;</span> <span class="k" id="mwlw">class</span><span class="w" id="mwmA"> </span><span class="nc" id="mwmQ">Person</span><span class="w" id="mwmg"> </span><span class="p" id="mwmw">{</span> <span class="k" id="mwnA">public</span><span class="o" id="mwnQ">:</span> <span class="w" id="mwng"> </span><span class="k" id="mwnw">virtual</span><span class="w" id="mwoA"> </span><span class="o" id="mwoQ">~</span><span class="n" id="mwog">Person</span><span class="p" id="mwow">()</span><span class="w" id="mwpA"> </span><span class="o" id="mwpQ">=</span><span class="w" id="mwpg"> </span><span class="k" id="mwpw">default</span><span class="p" id="mwqA">;</span> <span class="p" id="mwqQ">};</span> <span class="k" id="mwqg">class</span><span class="w" id="mwqw"> </span><span class="nc" id="mwrA">Employee</span><span class="o" id="mwrQ">:</span><span class="w" id="mwrg"> </span><span class="k" id="mwrw">public</span><span class="w" id="mwsA"> </span><span class="n" id="mwsQ">Person</span><span class="w" id="mwsg"> </span><span class="p" id="mwsw">{</span> <span class="w" id="mwtA"> </span><span class="c1" id="mwtQ">// ...</span> <span class="p" id="mwtg">};</span> <span class="kt" id="mwtw">int</span><span class="w" id="mwuA"> </span><span class="nf" id="mwuQ">main</span><span class="p" id="mwug">()</span><span class="w" id="mwuw"> </span><span class="p" id="mwvA">{</span> <span class="w" id="mwvQ"> </span><span class="n" id="mwvg">Person</span><span class="w" id="mwvw"> </span><span class="n" id="mwwA">person</span><span class="p" id="mwwQ">;</span> <span class="w" id="mwwg"> </span><span class="n" id="mwww">Employee</span><span class="w" id="mwxA"> </span><span class="n" id="mwxQ">employee</span><span class="p" id="mwxg">;</span> <span class="w" id="mwxw"> </span><span class="n" id="mwyA">Person</span><span class="o" id="mwyQ">*</span><span class="w" id="mwyg"> </span><span class="n" id="mwyw">ptr</span><span class="w" id="mwzA"> </span><span class="o" id="mwzQ">=</span><span class="w" id="mwzg"> </span><span class="o" id="mwzw">&</span><span class="n" id="mw0A">employee</span><span class="p" id="mw0Q">;</span> <span class="w" id="mw0g"> </span><span class="n" id="mw0w">Person</span><span class="o" id="mw1A">&</span><span class="w" id="mw1Q"> </span><span class="n" id="mw1g">ref</span><span class="w" id="mw1w"> </span><span class="o" id="mw2A">=</span><span class="w" id="mw2Q"> </span><span class="n" id="mw2g">employee</span><span class="p" id="mw2w">;</span> <span class="w" id="mw3A"> </span><span class="n" id="mw3Q">type_info</span><span class="w" id="mw3g"> </span><span class="n" id="mw3w">personType</span><span class="w" id="mw4A"> </span><span class="o" id="mw4Q">=</span><span class="w" id="mw4g"> </span><span class="k" id="mw4w">typeid</span><span class="p" id="mw5A">(</span><span class="n" id="mw5Q">person</span><span class="p" id="mw5g">);</span> <span class="w" id="mw5w"> </span><span class="n" id="mw6A">type_info</span><span class="w" id="mw6Q"> </span><span class="n" id="mw6g">employeeType</span><span class="w" id="mw6w"> </span><span class="o" id="mw7A">=</span><span class="w" id="mw7Q"> </span><span class="k" id="mw7g">typeid</span><span class="p" id="mw7w">(</span><span class="n" id="mw8A">employee</span><span class="p" id="mw8Q">);</span> <span class="w" id="mw8g"> </span><span class="n" id="mw8w">type_info</span><span class="w" id="mw9A"> </span><span class="n" id="mw9Q">ptrType</span><span class="w" id="mw9g"> </span><span class="o" id="mw9w">=</span><span class="w" id="mw-A"> </span><span class="k" id="mw-Q">typeid</span><span class="p" id="mw-g">(</span><span class="n" id="mw-w">ptr</span><span class="p" id="mw_A">);</span> <span class="w" id="mw_Q"> </span><span class="n" id="mw_g">type_info</span><span class="w" id="mw_w"> </span><span class="n" id="mwAQA">refType</span><span class="w" id="mwAQE"> </span><span class="o" id="mwAQI">=</span><span class="w" id="mwAQM"> </span><span class="k" id="mwAQQ">typeid</span><span class="p" id="mwAQU">(</span><span class="n" id="mwAQY">ref</span><span class="p" id="mwAQc">);</span> <span class="w" id="mwAQg"> </span> <span class="w" id="mwAQk"> </span><span class="c1" id="mwAQo">// The string returned by std::type_info::name() is implementation-defined.</span> <span class="w" id="mwAQs"> </span><span class="n" id="mwAQw">std</span><span class="o" id="mwAQ0">::</span><span class="n" id="mwAQ4">println</span><span class="p" id="mwAQ8">(</span><span class="s" id="mwARA">"{}"</span><span class="p" id="mwARE">,</span><span class="w" id="mwARI"> </span><span class="n" id="mwARM">personType</span><span class="p" id="mwARQ">.</span><span class="n" id="mwARU">name</span><span class="p" id="mwARY">());</span><span class="w" id="mwARc"> </span> <span class="w" id="mwARg"> </span><span class="c1" id="mwARk">// Person (statically known at compile-time).</span> <span class="w" id="mwARo"> </span><span class="n" id="mwARs">std</span><span class="o" id="mwARw">::</span><span class="n" id="mwAR0">println</span><span class="p" id="mwAR4">(</span><span class="s" id="mwAR8">"{}"</span><span class="p" id="mwASA">,</span><span class="w" id="mwASE"> </span><span class="n" id="mwASI">employeeType</span><span class="p" id="mwASM">.</span><span class="n" id="mwASQ">name</span><span class="p" id="mwASU">());</span><span class="w" id="mwASY"> </span> <span class="w" id="mwASc"> </span><span class="c1" id="mwASg">// Employee (statically known at compile-time).</span> <span class="w" id="mwASk"> </span><span class="n" id="mwASo">std</span><span class="o" id="mwASs">::</span><span class="n" id="mwASw">println</span><span class="p" id="mwAS0">(</span><span class="s" id="mwAS4">"{}"</span><span class="p" id="mwAS8">,</span><span class="w" id="mwATA"> </span><span class="n" id="mwATE">ptrType</span><span class="p" id="mwATI">.</span><span class="n" id="mwATM">name</span><span class="p" id="mwATQ">());</span><span class="w" id="mwATU"> </span> <span class="w" id="mwATY"> </span><span class="c1" id="mwATc">// Person* (statically known at compile-time).</span> <span class="w" id="mwATg"> </span><span class="n" id="mwATk">std</span><span class="o" id="mwATo">::</span><span class="n" id="mwATs">println</span><span class="p" id="mwATw">(</span><span class="s" id="mwAT0">"{}"</span><span class="p" id="mwAT4">,</span><span class="w" id="mwAT8"> </span><span class="n" id="mwAUA">refType</span><span class="p" id="mwAUE">.</span><span class="n" id="mwAUI">name</span><span class="p" id="mwAUM">());</span> <span class="w" id="mwAUQ"> </span><span class="c1" id="mwAUU">// Employee </span> <span class="w" id="mwAUY"> </span><span class="c1" id="mwAUc">// (looked up dynamically at run-time</span> <span class="w" id="mwAUg"> </span><span class="c1" id="mwAUk">// because it is the dereference of a</span> <span class="w" id="mwAUo"> </span><span class="c1" id="mwAUs">// pointer to a polymorphic class).</span> <span class="w" id="mwAUw"> </span> <span class="w" id="mwAU0"> </span><span class="n" id="mwAU4">std</span><span class="o" id="mwAU8">::</span><span class="n" id="mwAVA">println</span><span class="p" id="mwAVE">(</span><span class="s" id="mwAVI">"{}"</span><span class="p" id="mwAVM">,</span><span class="w" id="mwAVQ"> </span><span class="k" id="mwAVU">typeid</span><span class="p" id="mwAVY">(</span><span class="n" id="mwAVc">ref</span><span class="p" id="mwAVg">).</span><span class="n" id="mwAVk">name</span><span class="p" id="mwAVo">());</span> <span class="w" id="mwAVs"> </span><span class="c1" id="mwAVw">// Employee (references can also be polymorphic)</span> <span class="w" id="mwAV0"> </span><span class="n" id="mwAV4">Person</span><span class="o" id="mwAV8">*</span><span class="w" id="mwAWA"> </span><span class="n" id="mwAWE">p</span><span class="w" id="mwAWI"> </span><span class="o" id="mwAWM">=</span><span class="w" id="mwAWQ"> </span><span class="nb" id="mwAWU">nullptr</span><span class="p" id="mwAWY">;</span> <span class="w" id="mwAWc"> </span> <span class="w" id="mwAWg"> </span><span class="k" id="mwAWk">try</span><span class="w" id="mwAWo"> </span><span class="p" id="mwAWs">{</span> <span class="w" id="mwAWw"> </span><span class="k" id="mwAW0">typeid</span><span class="p" id="mwAW4">(</span><span class="o" id="mwAW8">*</span><span class="n" id="mwAXA">p</span><span class="p" id="mwAXE">);</span><span class="w" id="mwAXI"> </span><span class="c1" id="mwAXM">// Not undefined behavior; throws std::bad_typeid.</span> <span class="w" id="mwAXQ"> </span><span class="p" id="mwAXU">}</span><span class="w" id="mwAXY"> </span><span class="k" id="mwAXc">catch</span><span class="w" id="mwAXg"> </span><span class="p" id="mwAXk">(</span><span class="k" id="mwAXo">const</span><span class="w" id="mwAXs"> </span><span class="n" id="mwAXw">bad_typeid</span><span class="o" id="mwAX0">&</span><span class="w" id="mwAX4"> </span><span class="n" id="mwAX8">e</span><span class="p" id="mwAYA">)</span><span class="w" id="mwAYE"> </span><span class="p" id="mwAYI">{</span><span class="w" id="mwAYM"> </span> <span class="w" id="mwAYQ"> </span><span class="n" id="mwAYU">std</span><span class="o" id="mwAYY">::</span><span class="n" id="mwAYc">println</span><span class="p" id="mwAYg">(</span><span class="n" id="mwAYk">stderr</span><span class="p" id="mwAYo">,</span><span class="w" id="mwAYs"> </span><span class="s" id="mwAYw">"Exception caught: {}"</span><span class="p" id="mwAY0">,</span><span class="w" id="mwAY4"> </span><span class="n" id="mwAY8">e</span><span class="p" id="mwAZA">.</span><span class="n" id="mwAZE">what</span><span class="p" id="mwAZI">());</span> <span class="w" id="mwAZM"> </span><span class="p" id="mwAZQ">}</span> <span class="w" id="mwAZU"> </span><span class="n" id="mwAZY">Person</span><span class="o" id="mwAZc">&</span><span class="w" id="mwAZg"> </span><span class="n" id="mwAZk">ref2</span><span class="w" id="mwAZo"> </span><span class="o" id="mwAZs">=</span><span class="w" id="mwAZw"> </span><span class="o" id="mwAZ0">*</span><span class="n" id="mwAZ4">p</span><span class="p" id="mwAZ8">;</span><span class="w" id="mwAaA"> </span><span class="c1" id="mwAaE">// Undefined behavior: dereferencing null</span> <span class="w" id="mwAaI"> </span><span class="c1" id="mwAaM">// Does not meet requirements to throw std::bad_typeid</span> <span class="w" id="mwAaQ"> </span><span class="c1" id="mwAaU">// because the expression for typeid is not the result</span> <span class="w" id="mwAaY"> </span><span class="c1" id="mwAac">// of applying the unary * operator.</span> <span class="w" id="mwAag"> </span><span class="n" id="mwAak">type_info</span><span class="w" id="mwAao"> </span><span class="n" id="mwAas">ref2Type</span><span class="w" id="mwAaw"> </span><span class="o" id="mwAa0">=</span><span class="w" id="mwAa4"> </span><span class="k" id="mwAa8">typeid</span><span class="p" id="mwAbA">(</span><span class="n" id="mwAbE">ref2</span><span class="p" id="mwAbI">);</span> <span class="p" id="mwAbM">}</span>Output (exact output varies by system and compiler):
Person Employee Person* Employee Employee
C++ dynamic_cast and Java cast
The dynamic_cast operator in C++ is used for downcasting a reference or pointer to a more specific type in the class hierarchy. Unlike the static_cast, the target of the dynamic_cast must be a pointer or reference to class. Unlike static_cast and C-style typecast (where type check occurs while compiling), a type safety check is performed at runtime. If the types are not compatible, an exception will be thrown (when dealing with references) or a null pointer will be returned (when dealing with pointers).
A Java typecast behaves similarly; if the object being cast is not actually an instance of the target type, and cannot be converted to one by a language-defined method, an instance of java.lang.ClassCastException will be thrown.
Example
Suppose some function takes an object of type Base as its argument, and wishes to perform some additional operation if the object passed is an instance of Derived, a subclass of Base. This can be done using dynamic_cast as follows.
<span id="mwAeI"></span><span class="k" id="mwAeM">import</span><span class="w" id="mwAeQ"> </span><span class="n" id="mwAeU">std</span><span class="p" id="mwAeY">;</span> <span class="k" id="mwAec">using</span><span class="w" id="mwAeg"> </span><span class="n" id="mwAek">std</span><span class="o" id="mwAeo">::</span><span class="n" id="mwAes">array</span><span class="p" id="mwAew">;</span> <span class="k" id="mwAe0">using</span><span class="w" id="mwAe4"> </span><span class="n" id="mwAe8">std</span><span class="o" id="mwAfA">::</span><span class="n" id="mwAfE">bad_cast</span><span class="p" id="mwAfI">;</span> <span class="k" id="mwAfM">using</span><span class="w" id="mwAfQ"> </span><span class="n" id="mwAfU">std</span><span class="o" id="mwAfY">::</span><span class="n" id="mwAfc">unique_ptr</span><span class="p" id="mwAfg">;</span> <span class="k" id="mwAfk">class</span><span class="w" id="mwAfo"> </span><span class="nc" id="mwAfs">Foo</span><span class="w" id="mwAfw"> </span><span class="p" id="mwAf0">{</span> <span class="k" id="mwAf4">private</span><span class="o" id="mwAf8">:</span> <span class="w" id="mwAgA"> </span><span class="kt" id="mwAgE">void</span><span class="w" id="mwAgI"> </span><span class="n" id="mwAgM">specificToFoo</span><span class="p" id="mwAgQ">()</span><span class="w" id="mwAgU"> </span><span class="k" id="mwAgY">const</span><span class="w" id="mwAgc"> </span><span class="p" id="mwAgg">{</span> <span class="w" id="mwAgk"> </span><span class="n" id="mwAgo">std</span><span class="o" id="mwAgs">::</span><span class="n" id="mwAgw">println</span><span class="p" id="mwAg0">(</span><span class="s" id="mwAg4">"Method specific for Foo was invoked"</span><span class="p" id="mwAg8">);</span> <span class="w" id="mwAhA"> </span><span class="p" id="mwAhE">}</span> <span class="k" id="mwAhI">public</span><span class="o" id="mwAhM">:</span> <span class="w" id="mwAhQ"> </span><span class="c1" id="mwAhU">// Since RTTI is included in the virtual method table there should be at</span> <span class="w" id="mwAhY"> </span><span class="c1" id="mwAhc">// least one virtual function.</span> <span class="w" id="mwAhg"> </span><span class="k" id="mwAhk">virtual</span><span class="w" id="mwAho"> </span><span class="o" id="mwAhs">~</span><span class="n" id="mwAhw">Foo</span><span class="p" id="mwAh0">()</span><span class="w" id="mwAh4"> </span><span class="o" id="mwAh8">=</span><span class="w" id="mwAiA"> </span><span class="k" id="mwAiE">default</span><span class="p" id="mwAiI">;</span> <span class="p" id="mwAiM">};</span> <span class="k" id="mwAiQ">class</span><span class="w" id="mwAiU"> </span><span class="nc" id="mwAiY">Bar</span><span class="o" id="mwAic">:</span><span class="w" id="mwAig"> </span><span class="k" id="mwAik">public</span><span class="w" id="mwAio"> </span><span class="n" id="mwAis">Foo</span><span class="w" id="mwAiw"> </span><span class="p" id="mwAi0">{</span> <span class="k" id="mwAi4">public</span><span class="o" id="mwAi8">:</span> <span class="w" id="mwAjA"> </span><span class="kt" id="mwAjE">void</span><span class="w" id="mwAjI"> </span><span class="n" id="mwAjM">specificToBar</span><span class="p" id="mwAjQ">()</span><span class="w" id="mwAjU"> </span><span class="k" id="mwAjY">const</span><span class="w" id="mwAjc"> </span><span class="p" id="mwAjg">{</span> <span class="w" id="mwAjk"> </span><span class="n" id="mwAjo">std</span><span class="o" id="mwAjs">::</span><span class="n" id="mwAjw">println</span><span class="p" id="mwAj0">(</span><span class="s" id="mwAj4">"Method specific for Bar was invoked"</span><span class="p" id="mwAj8">);</span> <span class="w" id="mwAkA"> </span><span class="p" id="mwAkE">}</span> <span class="p" id="mwAkI">};</span> <span class="kt" id="mwAkM">void</span><span class="w" id="mwAkQ"> </span><span class="nf" id="mwAkU">qux</span><span class="p" id="mwAkY">(</span><span class="n" id="mwAkc">Foo</span><span class="o" id="mwAkg">&</span><span class="w" id="mwAkk"> </span><span class="n" id="mwAko">foo</span><span class="p" id="mwAks">)</span><span class="w" id="mwAkw"> </span><span class="p" id="mwAk0">{</span> <span class="w" id="mwAk4"> </span><span class="k" id="mwAk8">try</span><span class="w" id="mwAlA"> </span><span class="p" id="mwAlE">{</span> <span class="w" id="mwAlI"> </span><span class="c1" id="mwAlM">// Cast will be successful only for Bar type objects.</span> <span class="w" id="mwAlQ"> </span><span class="n" id="mwAlU">Bar</span><span class="o" id="mwAlY">&</span><span class="w" id="mwAlc"> </span><span class="n" id="mwAlg">bar</span><span class="w" id="mwAlk"> </span><span class="o" id="mwAlo">=</span><span class="w" id="mwAls"> </span><span class="k" id="mwAlw">dynamic_cast</span><span class="o" id="mwAl0"><</span><span class="n" id="mwAl4">Bar</span><span class="o" id="mwAl8">&></span><span class="p" id="mwAmA">(</span><span class="n" id="mwAmE">foo</span><span class="p" id="mwAmI">);</span> <span class="w" id="mwAmM"> </span><span class="n" id="mwAmQ">bar</span><span class="p" id="mwAmU">.</span><span class="n" id="mwAmY">specificToBar</span><span class="p" id="mwAmc">();</span> <span class="w" id="mwAmg"> </span><span class="p" id="mwAmk">}</span><span class="w" id="mwAmo"> </span><span class="k" id="mwAms">catch</span><span class="w" id="mwAmw"> </span><span class="p" id="mwAm0">(</span><span class="k" id="mwAm4">const</span><span class="w" id="mwAm8"> </span><span class="n" id="mwAnA">bad_cast</span><span class="o" id="mwAnE">&</span><span class="w" id="mwAnI"> </span><span class="n" id="mwAnM">e</span><span class="p" id="mwAnQ">)</span><span class="w" id="mwAnU"> </span><span class="p" id="mwAnY">{</span> <span class="w" id="mwAnc"> </span><span class="n" id="mwAng">std</span><span class="o" id="mwAnk">::</span><span class="n" id="mwAno">println</span><span class="p" id="mwAns">(</span><span class="n" id="mwAnw">stderr</span><span class="p" id="mwAn0">,</span><span class="w" id="mwAn4"> </span><span class="s" id="mwAn8">"Exception {} thrown."</span><span class="p" id="mwAoA">,</span><span class="w" id="mwAoE"> </span><span class="n" id="mwAoI">e</span><span class="p" id="mwAoM">.</span><span class="n" id="mwAoQ">what</span><span class="p" id="mwAoU">());</span> <span class="w" id="mwAoY"> </span><span class="n" id="mwAoc">std</span><span class="o" id="mwAog">::</span><span class="n" id="mwAok">println</span><span class="p" id="mwAoo">(</span><span class="s" id="mwAos">"Object is not of type Bar"</span><span class="p" id="mwAow">);</span> <span class="w" id="mwAo0"> </span><span class="p" id="mwAo4">}</span> <span class="p" id="mwAo8">}</span> <span class="kt" id="mwApA">int</span><span class="w" id="mwApE"> </span><span class="nf" id="mwApI">main</span><span class="p" id="mwApM">(</span><span class="kt" id="mwApQ">int</span><span class="w" id="mwApU"> </span><span class="n" id="mwApY">argc</span><span class="p" id="mwApc">,</span><span class="w" id="mwApg"> </span><span class="kt" id="mwApk">char</span><span class="o" id="mwApo">*</span><span class="w" id="mwAps"> </span><span class="n" id="mwApw">argv</span><span class="p" id="mwAp0">[])</span><span class="w" id="mwAp4"> </span><span class="p" id="mwAp8">{</span> <span class="w" id="mwAqA"> </span><span class="c1" id="mwAqE">// Array of pointers to base class Foo.</span> <span class="w" id="mwAqI"> </span><span class="n" id="mwAqM">array</span><span class="o" id="mwAqQ"><</span><span class="n" id="mwAqU">unique_ptr</span><span class="o" id="mwAqY"><</span><span class="n" id="mwAqc">Foo</span><span class="o" id="mwAqg">></span><span class="p" id="mwAqk">,</span><span class="w" id="mwAqo"> </span><span class="mi" id="mwAqs">3</span><span class="o" id="mwAqw">></span><span class="w" id="mwAq0"> </span><span class="n" id="mwAq4">foos</span><span class="w" id="mwAq8"> </span><span class="o" id="mwArA">=</span><span class="w" id="mwArE"> </span><span class="p" id="mwArI">{</span> <span class="w" id="mwArM"> </span><span class="n" id="mwArQ">std</span><span class="o" id="mwArU">::</span><span class="n" id="mwArY">make_unique</span><span class="o" id="mwArc"><</span><span class="n" id="mwArg">Bar</span><span class="o" id="mwArk">></span><span class="p" id="mwAro">();</span><span class="w" id="mwArs"> </span><span class="c1" id="mwArw">// Pointer to Bar object.</span> <span class="w" id="mwAr0"> </span><span class="n" id="mwAr4">std</span><span class="o" id="mwAr8">::</span><span class="n" id="mwAsA">make_unique</span><span class="o" id="mwAsE"><</span><span class="n" id="mwAsI">Bar</span><span class="o" id="mwAsM">></span><span class="p" id="mwAsQ">();</span><span class="w" id="mwAsU"> </span><span class="c1" id="mwAsY">// Pointer to Bar object.</span> <span class="w" id="mwAsc"> </span><span class="n" id="mwAsg">std</span><span class="o" id="mwAsk">::</span><span class="n" id="mwAso">make_unique</span><span class="o" id="mwAss"><</span><span class="n" id="mwAsw">Foo</span><span class="o" id="mwAs0">></span><span class="p" id="mwAs4">();</span><span class="w" id="mwAs8"> </span><span class="c1" id="mwAtA">// Pointer to Foo object.</span> <span class="w" id="mwAtE"> </span><span class="p" id="mwAtI">}</span> <span class="w" id="mwAtM"> </span><span class="k" id="mwAtQ">for</span><span class="w" id="mwAtU"> </span><span class="p" id="mwAtY">(</span><span class="n" id="mwAtc">Foo</span><span class="w" id="mwAtg"> </span><span class="n" id="mwAtk">f</span><span class="o" id="mwAto">:</span><span class="w" id="mwAts"> </span><span class="n" id="mwAtw">foos</span><span class="p" id="mwAt0">)</span><span class="w" id="mwAt4"> </span><span class="p" id="mwAt8">{</span> <span class="w" id="mwAuA"> </span><span class="n" id="mwAuE">qux</span><span class="p" id="mwAuI">(</span><span class="o" id="mwAuM">*</span><span class="n" id="mwAuQ">f</span><span class="p" id="mwAuU">);</span> <span class="w" id="mwAuY"> </span><span class="p" id="mwAuc">}</span> <span class="w" id="mwAug"> </span><span class="k" id="mwAuk">return</span><span class="w" id="mwAuo"> </span><span class="mi" id="mwAus">0</span><span class="p" id="mwAuw">;</span> <span class="p" id="mwAu0">}</span>Console output:
Method specific for Bar was invoked Method specific for Bar was invoked Exception std::bad_cast thrown. Object is not of type Bar
A similar version of qux() can be written with pointers instead of references:
<span id="mwAvY"></span><span class="kt" id="mwAvc">void</span><span class="w" id="mwAvg"> </span><span class="nf" id="mwAvk">qux</span><span class="p" id="mwAvo">(</span><span class="n" id="mwAvs">Foo</span><span class="o" id="mwAvw">*</span><span class="w" id="mwAv0"> </span><span class="n" id="mwAv4">foo</span><span class="p" id="mwAv8">)</span><span class="w" id="mwAwA"> </span><span class="p" id="mwAwE">{</span> <span class="w" id="mwAwI"> </span><span class="n" id="mwAwM">Bar</span><span class="o" id="mwAwQ">*</span><span class="w" id="mwAwU"> </span><span class="n" id="mwAwY">bar</span><span class="w" id="mwAwc"> </span><span class="o" id="mwAwg">=</span><span class="w" id="mwAwk"> </span><span class="k" id="mwAwo">dynamic_cast</span><span class="o" id="mwAws"><</span><span class="n" id="mwAww">Bar</span><span class="o" id="mwAw0">*></span><span class="p" id="mwAw4">(</span><span class="n" id="mwAw8">foo</span><span class="p" id="mwAxA">);</span> <span class="w" id="mwAxE"> </span><span class="k" id="mwAxI">if</span><span class="w" id="mwAxM"> </span><span class="p" id="mwAxQ">(</span><span class="n" id="mwAxU">derived</span><span class="p" id="mwAxY">)</span><span class="w" id="mwAxc"> </span><span class="p" id="mwAxg">{</span> <span class="w" id="mwAxk"> </span><span class="n" id="mwAxo">derived</span><span class="o" id="mwAxs">-></span><span class="n" id="mwAxw">specificToBar</span><span class="p" id="mwAx0">();</span> <span class="w" id="mwAx4"> </span><span class="p" id="mwAx8">}</span><span class="w" id="mwAyA"> </span><span class="k" id="mwAyE">else</span><span class="w" id="mwAyI"> </span><span class="p" id="mwAyM">{</span> <span class="w" id="mwAyQ"> </span><span class="n" id="mwAyU">std</span><span class="o" id="mwAyY">::</span><span class="n" id="mwAyc">println</span><span class="p" id="mwAyg">(</span><span class="n" id="mwAyk">stderr</span><span class="p" id="mwAyo">,</span><span class="w" id="mwAys"> </span><span class="s" id="mwAyw">"Object is not of type Bar"</span><span class="p" id="mwAy0">);</span> <span class="w" id="mwAy4"> </span><span class="p" id="mwAy8">}</span> <span class="p" id="mwAzA">}</span>Object Pascal, Delphi
In Object Pascal and Delphi, the operator is is used to check the type of a class at runtime. It tests the belonging of an object to a given class, including classes of individual ancestors present in the inheritance hierarchy tree (e.g. Button1 is a TButton class that has ancestors: TWinControl → TControl → TComponent → TPersistent → TObject, where the latter is the ancestor of all classes). The operator as is used when an object needs to be treated at run time as if it belonged to an ancestor class.
The RTTI unit is used to manipulate object type information at run time. This unit contains a set of classes that allow you to: get information about an object's class and its ancestors, properties, methods and events, change property values and call methods. The following example shows the use of the RTTI module to obtain information about the class to which an object belongs, creating it, and to call its method. The example assumes that the TSubject class has been declared in a unit named SubjectUnit.
<span id="mwA0Y"></span><span class="k" id="mwA0c">uses</span> <span class="w" id="mwA0g"> </span><span class="n" id="mwA0k">RTTI</span><span class="o" id="mwA0o">,</span><span class="w" id="mwA0s"> </span><span class="n" id="mwA0w">SubjectUnit</span><span class="o" id="mwA00">;</span> <span class="k" id="mwA04">procedure</span><span class="w" id="mwA08"> </span><span class="nf" id="mwA1A">WithoutReflection</span><span class="o" id="mwA1E">;</span> <span class="k" id="mwA1I">var</span> <span class="w" id="mwA1M"> </span><span class="n" id="mwA1Q">MySubject</span><span class="o" id="mwA1U">:</span><span class="w" id="mwA1Y"> </span><span class="n" id="mwA1c">TSubject</span><span class="o" id="mwA1g">;</span> <span class="k" id="mwA1k">begin</span> <span class="w" id="mwA1o"> </span><span class="n" id="mwA1s">MySubject</span><span class="w" id="mwA1w"> </span><span class="o" id="mwA10">:=</span><span class="w" id="mwA14"> </span><span class="n" id="mwA18">TSubject</span><span class="o" id="mwA2A">.</span><span class="n" id="mwA2E">Create</span><span class="o" id="mwA2I">;</span> <span class="w" id="mwA2M"> </span><span class="k" id="mwA2Q">try</span> <span class="w" id="mwA2U"> </span><span class="n" id="mwA2Y">Subject</span><span class="o" id="mwA2c">.</span><span class="n" id="mwA2g">Hello</span><span class="o" id="mwA2k">;</span> <span class="w" id="mwA2o"> </span><span class="k" id="mwA2s">finally</span> <span class="w" id="mwA2w"> </span><span class="n" id="mwA20">Subject</span><span class="o" id="mwA24">.</span><span class="n" id="mwA28">Free</span><span class="o" id="mwA3A">;</span> <span class="w" id="mwA3E"> </span><span class="k" id="mwA3I">end</span><span class="o" id="mwA3M">;</span> <span class="k" id="mwA3Q">end</span><span class="o" id="mwA3U">;</span> <span class="k" id="mwA3Y">procedure</span><span class="w" id="mwA3c"> </span><span class="nf" id="mwA3g">WithReflection</span><span class="o" id="mwA3k">;</span> <span class="k" id="mwA3o">var</span> <span class="w" id="mwA3s"> </span><span class="n" id="mwA3w">RttiContext</span><span class="o" id="mwA30">:</span><span class="w" id="mwA34"> </span><span class="n" id="mwA38">TRttiContext</span><span class="o" id="mwA4A">;</span> <span class="w" id="mwA4E"> </span><span class="n" id="mwA4I">RttiType</span><span class="o" id="mwA4M">:</span><span class="w" id="mwA4Q"> </span><span class="n" id="mwA4U">TRttiInstanceType</span><span class="o" id="mwA4Y">;</span> <span class="w" id="mwA4c"> </span><span class="n" id="mwA4g">Subject</span><span class="o" id="mwA4k">:</span><span class="w" id="mwA4o"> </span><span class="kt" id="mwA4s">TObject</span><span class="o" id="mwA4w">;</span> <span class="k" id="mwA40">begin</span> <span class="w" id="mwA44"> </span><span class="n" id="mwA48">RttiType</span><span class="w" id="mwA5A"> </span><span class="o" id="mwA5E">:=</span><span class="w" id="mwA5I"> </span><span class="n" id="mwA5M">RttiContext</span><span class="o" id="mwA5Q">.</span><span class="n" id="mwA5U">FindType</span><span class="p" id="mwA5Y">(</span><span class="s" id="mwA5c">'SubjectUnit.TSubject'</span><span class="p" id="mwA5g">)</span><span class="w" id="mwA5k"> </span><span class="k" id="mwA5o">as</span><span class="w" id="mwA5s"> </span><span class="n" id="mwA5w">TRttiInstanceType</span><span class="o" id="mwA50">;</span> <span class="w" id="mwA54"> </span><span class="n" id="mwA58">Subject</span><span class="w" id="mwA6A"> </span><span class="o" id="mwA6E">:=</span><span class="w" id="mwA6I"> </span><span class="n" id="mwA6M">RttiType</span><span class="o" id="mwA6Q">.</span><span class="n" id="mwA6U">GetMethod</span><span class="p" id="mwA6Y">(</span><span class="s" id="mwA6c">'Create'</span><span class="p" id="mwA6g">)</span><span class="o" id="mwA6k">.</span><span class="n" id="mwA6o">Invoke</span><span class="p" id="mwA6s">(</span><span class="n" id="mwA6w">RttiType</span><span class="o" id="mwA60">.</span><span class="n" id="mwA64">MetaclassType</span><span class="o" id="mwA68">,</span><span class="w" id="mwA7A"> </span><span class="p" id="mwA7E">[])</span><span class="o" id="mwA7I">.</span><span class="n" id="mwA7M">AsObject</span><span class="o" id="mwA7Q">;</span> <span class="w" id="mwA7U"> </span><span class="k" id="mwA7Y">try</span> <span class="w" id="mwA7c"> </span><span class="n" id="mwA7g">RttiType</span><span class="o" id="mwA7k">.</span><span class="n" id="mwA7o">GetMethod</span><span class="p" id="mwA7s">(</span><span class="s" id="mwA7w">'Hello'</span><span class="p" id="mwA70">)</span><span class="o" id="mwA74">.</span><span class="n" id="mwA78">Invoke</span><span class="p" id="mwA8A">(</span><span class="n" id="mwA8E">Subject</span><span class="o" id="mwA8I">,</span><span class="w" id="mwA8M"> </span><span class="p" id="mwA8Q">[])</span><span class="o" id="mwA8U">;</span> <span class="w" id="mwA8Y"> </span><span class="k" id="mwA8c">finally</span> <span class="w" id="mwA8g"> </span><span class="n" id="mwA8k">Subject</span><span class="o" id="mwA8o">.</span><span class="n" id="mwA8s">Free</span><span class="o" id="mwA8w">;</span> <span class="w" id="mwA80"> </span><span class="k" id="mwA84">end</span><span class="o" id="mwA88">;</span> <span class="k" id="mwA9A">end</span><span class="o" id="mwA9E">;</span>

