RTTI and type conversion, RTTI type conversion

Source: Internet
Author: User

RTTI and type conversion, RTTI type conversion
RTTIThrough runtime type recognition (RTTI), the program can use pointers or references of the base class to retrieve these pointers or reference the actual derived types of objects. The following two operators provide the RTTI: 1. typeid operator to return the actual type of the pointer or referenced object. 2. The dynamic_cast operator securely converts a pointer or reference of the base class type to a pointer or reference of the derived type. These operators only return dynamic type information for classes with one or more virtual functions. For other types, static (that is, compile-time) type information is returned. For classes with virtual functions, the RTTI operator is executed at runtime, but for other classes, the RTTI operator is calculated during compilation. When you have a base class reference or pointer but need to execute a derived class operation that is not part of the base class, you need to dynamically force type conversion. Generally, the best way to obtain a derived class from a base class pointer is to use a virtual function. When a virtual function is used, the compiler automatically selects the correct function based on the actual type of the object. However, in some cases, virtual functions cannot be used. In these cases, RTTI provides an optional mechanism. However, this mechanism is more error-prone than using virtual functions: the programmer must know the type of the object to be forcibly converted and check whether the conversion is successful. Be careful when using dynamic forced type conversion. Defining and using virtual functions is much better than directly taking over type management as long as possible.
Dynamic_castConverts a reference or pointer of a base class object to a reference or pointer of another type in the same inheritance level. Note: The class corresponding to the input dynamic_cast parameter must have a virtual function. Otherwise, compilation fails. Dynamic_cast involves the runtime type check. If the object bound to the reference or pointer is not of the target type, dynamic_cast fails. If the conversion to dynamic_cast of the pointer type fails, the result of dynamic_cast is 0. If the conversion to dynamic_cast of the reference type fails, a bad_cast type exception is thrown.
Typeid OperatorThe typeid expression is like typeid (e). Here e is an arbitrary expression or type name. If the expression type is a class type and the class contains one or more virtual functions, the dynamic type of the expression may be different from its static compilation type; the typeid operator can be used with any type of expression. Built-in expressions and constants can be used as the operands of the typeid operator. If the operand is not a class type or a class without a virtual function, the typeid operator specifies the static type of the operand. If the operand is a class type that defines at least one virtual function, the computing type at runtime.
The result of the typeid operator is an object reference of the standard library type named type_info. To use the type_info class, you must include the library header file typeinfo. The most common purpose of typeid is to compare the types of two expressions, or compare the expression type with the specific type: only when the typeid operand isObjects of the class type with virtual functionsDynamic type information is returned. The test pointer (relative to the object pointed to by the pointer) returns the static and compile-time type of the pointer. If the pointer p value is 0, if p type is a type with a virtual function, typeid (* p) throws a bad_typeid exception; if no virtual function is defined for the p type, the result is irrelevant to the p value. Just like the calculation expression sizeof, the compiler does not calculate * p. It uses the static type of p, which does not require p to be a valid pointer.
Instance

#include <iostream>#include <typeinfo>using namespace std;class Base{     public:          virtual void func(){cout << "I, Base." << endl;}};class Derived:public Base{     public:          void dfunc(){cout << "I, Derived." << endl;}};class BadDerived{     public:          virtual void func(){cout << "I, BadDerived." << endl;}};class T{     public:          void dfunc(){cout << "I, T." << endl;}};int main(){     Base *baseptr = new Derived;     BadDerived *badptr = new BadDerived;     cout << endl << "*********Test 0************" << endl;     if(T *deriveptr = dynamic_cast<T*>(baseptr))     {          cout << "success---->";          deriveptr->dfunc();     }     else     {          cout << "failed----->";          baseptr->func();          cout << "DEBUG" << endl;          cout << "typeid(T).name = " << typeid(T).name() << endl;          cout << "typeid(Baseref).name = " << typeid(*baseptr).name() << endl;     }     cout << endl << "*********Test 1************" << endl;     if(Derived *deriveptr = dynamic_cast<Derived*>(baseptr))     {          cout << "success---->";          deriveptr->dfunc();     }     else     {          cout << "failed----->";          baseptr->func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(*baseptr).name() << endl;     }     cout << endl << "*********Test 2************" << endl;     if(Derived *deriveptr = dynamic_cast<Derived*>(badptr))     {          cout << "success---->";          deriveptr->dfunc();     }     else                                 {                                         cout << "failed----->";          badptr->func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(*badptr).name() << endl;     }     Derived deriveobj;     Base &baseref = deriveobj;     BadDerived badobj;     BadDerived &badref = badobj;     cout << endl << "*********Test 3************" << endl;     try     {          Derived &deriveref = dynamic_cast<Derived&>(baseref);          cout << "success---->";          deriveref.dfunc();     }     catch(bad_cast)     {          cout << "failed----->";          baseref.func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(baseref).name() << endl;     }     cout << endl << "*********Test 4************" << endl;     try     {          Derived &deriveref = dynamic_cast<Derived&>(badref);          cout << "success---->";          deriveref.dfunc();     }     catch(bad_cast)     {          cout << "failed----->";          baseref.func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(badref).name() << endl;     }     cout << endl << "*********Test 5************" << endl;     if(typeid(Derived) == typeid(baseref))     {          Derived &deriveref = dynamic_cast<Derived&>(baseref);          cout << "success---->";          deriveref.dfunc();     }     else     {          cout << "failed----->";          baseref.func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(baseref).name() << endl;     }     cout << endl << "*********Test 6************" << endl;     if(typeid(Derived) == typeid(badref))     {          Derived &deriveref = dynamic_cast<Derived&>(badref);          cout << "success---->";          deriveref.dfunc();     }     else     {          cout << "failed----->";          badref.func();          cout << "DEBUG" << endl;          cout << "typeid(Derived).name = " << typeid(Derived).name() << endl;          cout << "typeid(Baseref).name = " << typeid(badref).name() << endl;     }}

Execution result ********** Test 0 ************
Failed -----> I, Base.
DEBUG
Typeid (T). name = 1 T
Typeid (Baseref). name = 7 Derived

* ******** Test 1 ************
Success ----> I, Derived.

* ******** Test 2 ************
Failed -----> I, BadDerived.
DEBUG
Typeid (Derived). name = 7 Derived
Typeid (Baseref). name = 10 BadDerived

* ******** Test 3 ************
Success ----> I, Derived.

* ******** Test 4 ************
Failed -----> I, Base.
DEBUG
Typeid (Derived). name = 7 Derived
Typeid (Baseref). name = 10 BadDerived

* ******** Test 5 ************
Success ----> I, Derived.

* ******** Test 6 ************
Failed -----> I, BadDerived.
DEBUG
Typeid (Derived). name = 7 Derived
Typeid (Baseref). name = 10 BadDerived
Type conversion
C Style conversion is a "universal conversion", but programmers need to grasp the security of conversion, and the compiler is powerless.
The security of type conversion comes from two aspects: one is narrow type conversion, which will lead to the loss of data digits; the other is in the class inheritance chain, forcibly convert the address (pointer) of the parent class object to the address (pointer) of the Child class. This is the so-called downlink conversion, "bottom" indicates that the inheritance chain goes down (to the subclass direction ). Similarly, the "up" of the uplink conversion indicates that the uplink is going up along the inheritance chain (to the parent class). The uplink conversion is generally safe, and the downlink conversion is probably insecure; because the subclass contains the parent class, the uplink conversion (only the method of the parent class can be called to reference the member variables of the parent class) is generally safe. However, the parent class does not have any information about the subclass. the downlink conversion calls the subclass method and references the member variables of the subclass. None of these parent classes exist, therefore, it is easy to refer to the deer as a horse or point to a memory space that does not exist.Static_cast <new_type> (expression) static conversion

Static_cast Closest C Style conversion, but the compiler reports an error during irrelevant class pointer conversion, improving security.Dynamic_cast <new_type> (expression) dynamic conversion dynamic conversion ensures that class pointer conversion is appropriate and complete. It has two important constraints. One is that new_type is a pointer or reference, the second is that the base class is polymorphism (the base class contains at least one virtual function) in the downstream conversion ), If the downlink conversion is insecure, Dynamic_cast Returns Null Pointer. If the pointer to be converted is void * or the target pointer is void *, dynamic_cast always considers it safe. Reinterpret_cast <new_type> (expression) re-interpreting the conversion is the most "insecure". The conversion can be used between two class pointers without any relationship. Reinterpret_cast can convert an integer to an address (pointer). This type of conversion is performed at the underlying system level, which has strong platform dependence and poor portability. It also requires that new_type be a pointer or reference. Const_cast <new_type> (expression) constant converts to a non-Constant Const_cast You can convert a constant to a non-constant without damaging the original constant. Const Attribute, only return a remove Const .From char * cc = const_cast <char *> (c), we can see the role of this conversion, but remember that this conversion does not convert the original constant itself, that is, c or constant, it only returns the non-constant cc.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.