Reprinted URL: http://www.cppblog.com/smagle/archive/2010/05/14/115286.aspx
Before unlocking the mystery of typeid, let's take a look at rtti (run-time type identification, runtime type recognition ), it enables the program to obtain the actual derived type of the object pointed to by a base pointer or reference, that is, the program that allows the operation of objects by pointer or reference to the base class can obtain the actual derived type of the pointer or reference to the objects. In C ++, two operators are provided to support rtti: dynamic_cast and typeid.
Dynamic_cast allows type conversion at runtime, so that the program can safely convert the type in a class hierarchy. Correspondingly, there is a non-secure conversion operator static_cast, this is not the focus of this article, so we will not detail it here. If you are interested, you can check the information on your own. Let's start today's topic: typeid.
Typeid is one of the keywords of C ++, which is equivalent to operators such as sizeof. The return result of the typeid operator is a reference to an object of the standard library type named type_info (defined in the header file typeinfo. Let's take a look at the source code in the Vs and GCC libraries later ), its Expression has two forms.
If the expression type is a class type and contains at least one virtual function, the typeid operator returns the dynamic type of the expression, which must be calculated at runtime. Otherwise, the typeid operator returns the static type of the expression, it can be computed during compilation.
The iso c ++ standard does not have the exact definition of type_info, which defines compiler-related, however, the standard specifies that the implementation must provide the following four operations (in the subsequent sections, I will analyze the source code of the type_info class file ):
| T1 = t2 |
If the T1 and T2 objects are of the same type, true is returned; otherwise, false is returned. |
| T1! = T2 |
If the T1 and T2 types of the two objects are different, true is returned; otherwise, false is returned. |
| T. Name () |
Returns the C-style string of the type. The type name is generated using a system-related method. |
| T1.before (T2) |
Returns the bool value indicating whether T1 exists before T2. |
The type_info class provides public virtual destructor so that users can use it as the base class. Its default constructor, copy constructor, and value assignment operator are both defined as private. Therefore, objects of the type_info type cannot be defined or copied. The only way to create a type_info object in the program is to use the typeid operator (it can be seen that if typeid is treated as a function, it should be the friend of type_info ). The name member function of type_info returns the C-style string to indicate the corresponding type name, however, it is important to note that the returned type name is not necessarily consistent with the corresponding type name used in the Program (this is often the case, see the program below), which is determined by the implementation of the compiler, the standard only requires that a unique string be returned for each type.
The above are some theoretical things that are not really true. The following code and legends will be used for demonstration.
# Include <iostream>
Using namespace STD;
Class base {};
Class derived: public base {};
Int main ()
{
Base B, * pb;
PB = NULL;
Derived D;
Cout <typeid (INT). Name ()
<Endl
<Typeid (unsigned). Name ()
<Endl
<Typeid (long). Name ()
<Endl
<Typeid (unsigned long). Name ()
<Endl
<Typeid (char). Name ()
<Endl
<Typeid (unsigned char). Name ()
<Endl
<Typeid (float). Name ()
<Endl
<Typeid (double). Name ()
<Endl
<Typeid (string). Name ()
<Endl
<Typeid (base). Name ()
<Endl
<Typeid (B). Name () <Endl
<Typeid (PB). Name () <Endl
<Typeid (derived). Name () <Endl
<Typeid (d). Name () <Endl
<Typeid (type_info). Name ()
<Endl;
Return 0;
}
I used V8 of MS and GCC of gun to compile and run the code. The results are the left and right figures below.
Comparing the code and the text description above, I don't know if you have made it clear (here we need to note that the base class object B and the Object Pointer Pb, their output ).
Considering that V8 outputs are intuitive, I use V8 to perform experiments. Add a little content to the above Code as follows:
Base * PBS = dynamic_cast <Base
*> (New derived );
Base & b2 = D;
Base * PB3 = & D;
Cout <typeid (PBS). Name ()
<Endl // output base *
<Typeid (B2). Name () <Endl // output base
<Typeid (PB3). Name () <Endl // output base *
<Typeid (* PB3). Name () <Endl; // output base
Because base does not contain virtual functions, the result of typeid indicates that the expression type is base or base *, although their underlying object is derived. That is, when the operand of the typeid operator is a class type without a virtual function, the typeid operator indicates the type of the operand rather than the type of the underlying object.
Next we will make a small adjustment to the base function, add a virtual function to it, and then look at the output result.
Class base {virtual
Void F (){};};
/*...*/
Cout <typeid (PBS). Name ()
<Endl // output base *
<Typeid (B2). Name () <Endl // output derived
<Typeid (PB3). Name () <Endl // output base *
<Typeid (* PB3). Name () <Endl; // output derived
This time, the base contains virtual functions. Note that the pointer is still base *. Although they point to the underlying object derived, the type of these base objects is derived.
Because pointer PB3 is not a class type, typeid returns the pointer type base * of pointer PB3 *. * PB3 is a class expression with a virtual function. Therefore, it indicates the type of the underlying object to which PB3 points.
If the operand of the typeid operator is a class type that contains at least one virtual function and the expression is a base class application, the typeid operator indicates the type of the derived class of the underlying object.
Now, let's end with a few small questions.
// Use the V8 Environment
Cout <typeid (7.84). Name () <Endl
<Typeid (base *). Name () <Endl
<Typeid (& PB3). Name () <Endl;