C + + language learning (19)--c++ type recognition

Source: Internet
Author: User

C + + language learning (19)--c++ type recognition, Introduction to C + + type recognition 1, Introduction to C + + type recognition

C + + is a statically typed language whose data type is determined at compile time and cannot be changed at run time.
In the C + + language, a static type is the type of the object itself, and the dynamic type is the actual type of the object pointed to by the pointer (reference).
RTTI (run-time type information) is run-time type aware, and C + + supports polymorphic support through RTTI.
To support rtti,c++ provides a type_info class and typeid with dynamic_cast two keywords.

2. Type_info Structural Body

Type_info:
Information about the types of features stored, commonly used to compare object types, the specific content of the Type_info class is determined by the compiler implementation. The statement is as follows:

class type_info {public:    virtual ~type_info();    bool operator== (const type_info& rhs) const;    bool operator!= (const type_info& rhs) const;    bool before (const type_info& rhs) const;    const char* name() const;private:    type_info (const type_info& rhs);    type_info& operator= (const type_info& rhs);};

Type_info constructors and assignment operators are private, so the only way to create Type_info objects in a program is to use the typeid operator. The C + + standard simply tells the compiler to implement the Type_info::name function, but different compiler implementations vary, so the typeid (int). Name () differs from the compiler after the compiler runs the output.

3. typeID Key Words

typeID
  typeid语法规则如下:typeid(expr);
The typeid expression returns the Type_info type, and expr can be an instance, pointer, or reference to various type names, objects, and built-in base data types. When used as pointers and references, the type information that actually points to the object is returned.
If the type of the expression is a class type and contains at least one virtual function, the typeid operator returns the dynamic type of the expression, which needs to be determined at run time, otherwise the typeid operator returns the static type of the expression, which can be determined at compile time.
When the typeid is applied to the pointer's dereference p, if the pointer p is 0, then if the type P is pointing to is a class type with a virtual function, then typeid (p) throws a Bad_typeid exception at run time; otherwise, typeid (*p) The result is not related to the value of P and can be determined at compile time.

4. dynamic_cast Key Words

dynamic_cast:
Dynamic type conversions, run-time type security checks. Dynamic_cast checks whether the source object being converted can actually be converted to the target type, which is not syntactically, but true. Many compilers find the RTTI information of an object by vtable, and if the base class does not have a virtual method, it is impossible to determine the true type of the object to which a base class pointer variable refers.
dynamic_cast converts a pointer to a base class to a pointer to a derived class, and returns a null pointer if it cannot be converted correctly.
The C + + language provides the typeID keyword for obtaining type information, and the typeID keyword returns the type information for the corresponding parameter. typeID returns an Type_info class object that throws an exception when the argument to typeID is null. The typeID parameter can be either a type or a variable, when the parameter is a type, return static type information, when the argument is a variable, if there is no virtual function table, returns the static type information, if there is a virtual function table, returns the dynamic type information.
The return result of the typeid operator is a reference to an object of the standard library type named Type_info.
typeID is different in different C + + compiler implementations.

RTTI (run-time type identification, run-time types identification)

Second, C + + type conversion

C + + type conversions are divided into up-type conversions and down-type conversions.

1, Upward type conversion

In the C + + language, an up-type conversion describes a forced type conversion of a subclass to a base class, which is an implicit type conversion. In the upward type conversion process, the phenomenon of overwriting methods and sub-class object data loss is called cutting.

#include <iostream>using namespace std;class Base{public:    Base(int value = 0)    {        data = value;    }    virtual void print()    {        cout << "Base::print data = " << data << endl;    }protected:    int data;};class Derived : public Base{public:    Derived(int value = 0)    {        data = value;    }    virtual void print()    {        cout << "Derived print data = " << data << endl;    }protected:    int data;};int main(int argc, char *argv[]){    Derived d(100);    //将子类向上转型为基类    Base b = d;//直接赋值,产生切割    b.print();//Base::print data = 0    Base& rb = d;//引用赋值,不产生切割    rb.print();//Derived print data = 100    Base* pb = &d;//指针赋值,不产生切割    pb->print();//Derived print data = 100    //Derived* dp = pb;//error,不允许隐式向下转型    return 0;}

Using pointers and references does not cause cuts during the up-casting process, and using direct assignments can cause cuts.

2, down type conversion

In the

C + + language, the down-type conversion describes a forced type conversion of a base class to a subclass, forcing a type conversion downward using dynamic_cast. Dynamic_cast will perform type checking at run time. If the downward transformation is safe (if the base class pointer or reference actually refers to an object of a derived class), dynamic_cast returns the type-converted pointer. dynamic_cast returns a null pointer if the downward transition is unsafe (that is, the base class pointer or the reference does not point to an object of a derived class). When you use dynamic_cast, you must define a virtual function in your class.

#include <iostream>using namespace Std;class base{public:base (int value = 0) {data = value;    } virtual void print () {cout << "Base::p rint data =" << data << Endl; }protected:int data;};    Class Derived:public base{public:derived (int value = 0) {data = value;    } virtual void print () {cout << "Derived Print data =" << data << Endl; }protected:int data;};    int main (int argc, char *argv[]) {//pointer base* BP1 = new Base (101);    derived* dp11 = static_cast<derived*> (BP1);    cout << "Base" << Endl;    cout << BP1 << Endl;    cout << dp11<< Endl;    Dp11->print ();//base::p rint data = 101 derived* DP12 = dynamic_cast<derived*> (BP1);    cout << dp12 << endl;//0, down transition failed if (DP12! = NULL) {dp12->print ();    } base* bp2 = new Derived (102);    derived* dp21 = static_cast<derived*> (BP2); COut << "Derived" << Endl;    cout << bp2 << Endl;    cout << dp21<< Endl;    Dp21->print ();//derived Print data = 102 derived* dp22 = dynamic_cast<derived*> (BP2);     cout << dp22 << endl;//down transition success if (dp22! = NULL) {dp22->print ();//derived Print data = 102}    Reference Base B1 (10);    derived& rd11 = static_cast<derived&> (B1); Rd11.print ();//base::p rint data =//derived& rd12 = dynamic_cast<derived&> (B1);//exception Derived    B2 (10);    derived& rd21 = static_cast<derived&> (B2);    Rd21.print ();//derived print data = derived& Rd22 = dynamic_cast<derived&> (B2); Rd22.print ();//derived print data = 0 return;}

In the code above, if pointers, references actually point to objects that are derived class objects, using static_cast, dynamic_cast conversions are safe, and if pointers, references actually point to objects that are base class objects, using dynamic_cast returns a null pointer or throws an exception. Use the Static_cast keyword to return a pointer or reference that executes a base class object, and you cannot access the overridden methods and members of a derived class.

3, multi-inheritance of the downward transformation
#include <iostream>using namespace Std;class basea{public:basea (int value = 0) {data = value;    } virtual void PrintA () {cout << "Basea::p rint data =" << data << Endl; }protected:int data;};    Class Baseb{public:baseb (int value = 0) {data = value;    } virtual void Printb () {cout << "BASEB::p rint data =" << data << Endl; }protected:int data;};    Class Derived:public Basea, public baseb{public:derived (int value = 0) {data = value;    } virtual void PrintA () {cout << "Derived printA data =" << data << Endl;    } virtual void Printb () {cout << "Derived printb data =" << data << Endl; }protected:int data;};    int main (int argc, char *argv[]) {//basea cout << "Basea" << Endl;    basea* BPA = new Basea (10);    cout << BPA << Endl; derived* PD1 = Static_cast<deriVed*> (BPA);    cout << pd1 << Endl; Pd1->printa ();//BASEB::p rint data//pd1->printb ();//exception, actually pointing to Basea object, no Printb method derived* PD2 = dynamic    _cast<derived*> (BPA);        cout << pd2 << endl;//0, down transition failed if (pd2! = NULL) {Pd2->printa ();    PD2-&GT;PRINTB ();    }//baseb cout << "Baseb" << Endl;    baseb* BPB = new Baseb (10);    cout << BPB << Endl;    Pd3 points to bpb the first 8 bytes of address derived* pd3 = static_cast<derived*> (BPB);    cout << pd3 << Endl;    Pd3->printa ();//exception//pd3->printb ();//exception derived* pd4 = dynamic_cast<derived*> (BPB);        cout << pd4 << endl;//0, down transition failed if (pd4! = NULL) {Pd4->printa ();    PD4-&GT;PRINTB ();    } cout << "Derived" << Endl;    basea* bpd = new Derived (101);    cout << bpd << Endl;    derived* pd5 = static_cast<derived*> (bpd); cout << pd5 << Endl; Pd5->printa ();//derived PrintA data = 101 pd5->printb ();//derived PRINTB data = 101 derived* Pd6 = Dynamic_cas    T<derived*> (bpd);    cout << pd6 << Endl; if (pd6! = NULL) {Pd6->printa ();//derived PrintA data = 101 pd6->printb ();//derived PRINTB data = 1    basea* pa = static_cast<basea*> (bpd);    Pa->printa (); baseb* PB = static_cast<baseb*> (bpd),//error, baseb* PB = dynamic_cast<baseb*> (bpd);//correct, Pb->print    B ();    cout << "derived+" << Endl;    derived* DPD = new Derived (102);    cout << DPD << Endl;    basea* dpa = static_cast<basea*> (DPD);    cout << dpa << Endl;    Dpa->printa ();    baseb* DPB1 = static_cast<baseb*> (DPD);//cout << dpb1 << Endl;    DPB1-&GT;PRINTB ();    baseb* DPB2 = dynamic_cast<baseb*> (DPD);//cout << dpb2 << Endl;    DPB2-&GT;PRINTB (); return 0;}

In the code above, the BPA pointer points to the Basea object, and when you use the Static_cast keyword to convert a BPA downward to a derived pointer object, the value of BPA is returned, because the Basea object is actually pointed to, so the Baseb method causes an exception; use Dynamic_ When the cast keyword is transitioning to BPA, the transformation fails and returns NULL.
The BPB pointer actually points to the Baseb object, and when you use the Static_cast keyword to convert a BPB downward to a derived pointer object, return the address of the 8 byte of the BPB address, which is an illegal derived object address, so call Basea, The Baseb class method causes an exception, and when you use the DYNAMIC_CAST keyword to transform a BPA down, the transformation fails and returns NULL.
The BPD pointer actually points to the derived object, and when you use the Static_cast keyword to transform a bpd downward into a derived pointer object, the value of the BPD is returned, and the method of Basea, BASEB class can be legitimately invoked; using Dynamic_ When the CAST keyword moves down the BPD, the value of the BPD is returned, and the method of the Basea, BASEB class can be legitimately invoked. If you use the Static_cast keyword to transform the Basea type pointer bpd to a BASEB pointer, the C + + compiler will give an error; You must use the dynamic_cast keyword, and dynamic_cast adjusts the pointer at run time.
The DPD pointer of the derived type points to the derived object, which can be transformed up using the Static_cast keyword and the dynamic_cast keyword.

Iii. the introspection mechanism of C + +

Introspection refers to the ability of an object-oriented language to query object information during runtime, such as if the language has the ability to check object type during runtime, then the language is type intropection, and type introspection can be used to implement polymorphism.
The introspection of C + + is limited, only supports type introspection, and the type introspection of C + + is achieved through the typeID in runtime type Recognition (RTTI) (run-time type information) and the Dynamic_case keyword.

C + + language learning (19)--c++ type recognition

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.