Type identifier (typeid)
A new feature of Standard C ++ is rtti (run-time type information runtime type information), which provides a standard method for programs to determine the object type during runtime. In standard C ++, there are three elements supporting rtti:
<! -- [If! Supportlists] --> 1. <! -- [Endif] --> keyword dynamic_cast (Dynamic forced conversion): The operator dynamic_cast converts a pointer to the base class to a pointer to the derived class (if the conversion is not correct, returns 0 -- NULL pointer) in the format:
Dynamic_cast <type-ID> (exdivssion)
Dynamic_cast must use the type information class type_info of the relevant class during the conversion process. This keyword is already described in section 1.2 in the previous section.
<! -- [If! Supportlists] --> 2. <! -- [Endif] --> keyword typeid (type identifier): used to detect pointer types (return pointer of type_info Class Object), format:
Typeid (exdivssion) or typeid (Type-ID)
Exdivssion is the expression for the result object, and type-ID is the class name.
<! -- [If! Supportlists] --> 3. <! -- [Endif] --> class type_info (type information): stores information about a specific type, which is defined in the header file <typeinfo>. The specific content of the type_info class is determined by the compiler implementation, but it must contain at least the name () member function of the returned string. The following is the vc05 implementation version of The type_info class:
Simplified definition in class type_info {// vc05
Public:
Virtual ~ Type_info ();
Bool operator = (const type_info & RHs) const;
Bool Operator! = (Const type_info & RHs) const;
Int before (const type_info & RHs) const;
Const char * Name () const;
Const char * raw_name () const;
PRIVATE:
Void * _ m_data;
Char _ m_d_name [1];
Type_info (const type_info & RHs );
Type_info & operator = (const type_info & RHs );
Static const char * _ name_base (const type_info * prhs, _ type_info_node * _ ptype_info_node );
Static void _ type_info_dtor (type_info * prhs );
};
For example: (create a "Visual C ++/regular/Empty Project" project named TMP and add the following two files to the project)
// TMP. h
Template <class T> Class {};
// TMP. cpp
# Include <typeinfo. h>
# Include <iostream>
# Include "tmp. H"
Using namespace STD;
Int main (){
A <int>;
A <char> B;
Cout <typeid (a). Name () <Endl;
Cout <typeid (B). Name () <Endl;
If (typeid (A) = typeid (B) cout <"A = B" <Endl;
Else cout <"! = B "<Endl;
Cout <Endl;
Int I;
Cout <typeid (INT). Name () <Endl;
Cout <typeid (I). Name () <Endl;
If (typeid (INT) = typeid (I) cout <"typeid (INT) = typeid (I)" <Endl;
Else cout <"typeid (INT )! = Typeid (I) "<Endl;
Cout <Endl;
}
Output result:
Class A <int>
Class A <char>
A! = B
Int
Int
Typeid (INT) = typeid (I)
Note: Only rtti can be used for abstract class levels that contain virtual functions.
8) type name (typename)
Identifiers in some Nested classes should have been processed as types, but the compiler does not know this, but may regard it as a static variable.
For an identifier that appears in the template, if the compiler can treat it as a type and treat it as a variable, object, enumeration, function, or template, the compiler generally does not regard this identifier as a type and considers it as another element (such as a variable or object ).
The solution is to use the standard C ++ keyword typename to explicitly tell the compiler that its identifier is a type name, rather than anything else.
For example:
Template <class T> Class X {
Typename T: id I; // if no typename is provided, the compiler regards T: ID as a static variable.
Public:
Void F () {I. g ();}
};
Class y {
Public:
Class ID {
Public:
Void g (){}
};
};
Int main (){
X <Y> XY;
XY. F ();
}
The last usage is to use typename instead of the type parameter class in the template declaration.
Template <class T> ......
Change
Template <typename T> ......
In addition, this is more accurate. In addition to the class type, the basic data type and structure can also be used as template type parameters.
Example: (function templates that can print data in any standard C ++ sequence container)
// Printseq. cpp
# Include <iostream>
# Include <list>
# Include <memory>
# Include <vector>
Using namespace STD;
Template <class T, template <Class U, class = Allocator <u> class seq>
Void printseq (SEQ <t> & SEQ ){
For (typename seq <t>: iterator B = seq. Begin (); B! = Seq. End (); B ++)
Cout <* B <Endl;
}
Int main (){
// Process the Vector
Vector <int> V;
V. push_back (1); V. push_back (2 );
Printseq (v );
// Process the table
List <int> lst;
Lst. push_back (3); lst. push_back (4 );
Printseq (LST );
}
Output:
1
2
3
4
Note: The keyword typename cannot create a new type name. It only notifies the compiler to interpret the identifier as a type. To create a new type name, you can use the keyword typedef. For example
Typename seq <t>: iterator it; // tells the compiler that iterator is a type and it is a variable of this type.
Typedef typename seq <t>: iterator it; // creates a new type name equivalent to iterator it