Since 1993 Bjarne stroustrup(Note 1) proposed the RTTI function of C + +, and exception handling for C + + (exception handling) requires Rtti; recently introduced C + + has more or less provided rtti. However, if Rtti is accidentally used, it may result in a decrease in software elasticity. This article will introduce the concept and current situation of rtti, and explain how to use it.
What is rtti?
in C + + environment, header file contains class definition That is, contains the structure information about the class (representational information). However, this information is only used by the compiler (compiler) and is not left behind after compilation, so at execution time (at Run-time), the object's class data is not known, including the class name, data member name and type, function name and type, and so on. For example, a two-class figure and a circle, are inherited relationships.
If the following command:
Figure *p;
p = new Circle ();
Figure &q = *p;
,p points to an object at execution time, but it is difficult to learn about the object. Also want to know the Q reference (Reference) object of the class data, can not be obtained. RTTI (run-time type identification) is to solve this difficulty, that is, when executing, you want to know when the pointer refers to or reference to the object type, the object has the ability to tell you. The range of Rtti you need to support varies depending on the application. The simplest rtti include:
class identification--including the class name or ID.
Inheritance relationship (inheritance relationship)--supports the "Down transformation type" (downward casting) of the execution period, i.e. dynamic transformation type (dynamically casting) .
In the object database access, the following rtti: are also required
Object Layout-includes the type, name, and location of the property (position or offset).
member function table (table of functions)-includes the type of function, its name, its parameter type, and so on.
The purpose is to assist in the I/O and persistence of objects (persistence), as well as debug messages.
In accordance with the recommendations of Bjarne Stroustrup (note 1),c++ should also include a more complete rtti:
The objects to which the class is instantiated.
can refer to the source code of the function.
Can obtain the relevant online description of the class (on-line documentation).
These are all the data that was discarded when C + + was compiled, and now we just want to find a way to keep it for the duration of execution. However, to provide a complete rtti, will greatly increase the complexity of C + +!
Rtti may be accompanied by side effects
The main side-effect of RTTI is that programmers might use Rtti to support their "check" (multiple-selection) methods instead of virtual functions (virtual function).
Although both methods can achieve polymorphism (polymorphism), using a check method often leads to a violation of the famous "open/Closed principle" (open/closed principle) (Note 2). Conversely, the use of virtual function method can conform to this principle.
Circle and Square are all subclasses derived from figure, each of which has its own draw () function. When C + + provides rtti,, you can write a function like this:
void drawing (Figure *p)
{
if (typeID (*p). Name () = = "Circle")
((circle*) p), Draw ();
if (typeID (*p). Name () = = "Rectangle")
((rectangle*) p), Draw ();
}
Although the drawing () function is also multi-type, it is closely related to the structure of the figure class System. The contents of the,drawing () function must have an additional if directive when the figure class system is derived from the child class. Thus violating the "open/Closed principle" ", as follows:
It is clear that the,drawing () function should be corrected.
Consider that if C + + does not provide rtti, the programmer has no choice but to use virtual functions to support the drawing () function's polymorphism. The programmer then declares the draw () as a virtual function and writes drawing () as follows:
void drawing (Figure *p)
{P->draw ();}
So the,figure class system can derive classes at any time without having to fix the drawing () function. That is, the,figure system has a stable interface (interface),drawing () using this interface, so that the drawing () function is also stable, will not be changed with the expansion of the figure class System. This is the closed side. This stable interface does not limit the growth of the figure system, which is an open side. Thus, the "open/closed" principle makes the software more resilient and more prone to growing with the environment.
common use cases of Rtti
In general, there are four common use cases for,rtti: exception Handling (exceptions handling), dynamic Transfer type (dynamics casting), module integration, and object I/O .
1. Exception handling-A familiar new C + + feature: Exception handling, which requires rtti, such as the class name.
2. Dynamic turn type-in class hierarchy, the downward type conversion requires class-inherited Rtti.
3. Module integration-How do you know the identity of an object in a program module when you want to communicate with the object of another program module? Knowing its identity can call its function. General C + + programs, the common solution is to--in the source code, such as the object of the other definition (i.e., there is a header file) included, at compile time to link work. However, as in the current popular master-slave (client-server) architecture, client-side module objects often need to communicate with the off-the-shelf module objects of the host side (Server), which must communicate at execution time, but often cannot be recompiled repeatedly. So the class definition data provided by the header file is not conducive to the communication work at the time of execution, but relies on the rtti.
4. Object i/o──c++ programs often store their objects in the database and can be read in the future. Objects often contain other small objects, so in the database, in addition to know the name of the class to which the object belongs, you must know the class containing the small object, in order to completely save the object in. These rtti data are also stored in the database along with the object content. When you read objects in the future, you can allocate memory space to objects based on these rtti data.
where does Rtti come from?
The above talks about the use of Rtti, as well as its side effects. The controversy has made the RTTI standard slow to emerge. Also leads to the various C + + development environment providers that support rtti, in a variety of ways, depending on their environment, and the range of support Rtti is different. The current common support methods include:
A Visual C + + environment for rtti── such as,microsoft company is provided by the class library.
provided by the C + + compiler (compiler)-for example, version,borland C + + 4.5.
Provided by the Source code generator (code generator), such as the BELLVOBR system.
Provided by the special preprocessor (preprocessor) of the OO database-for example, the poet system.
Added by the programmer himself.
These methods provide only a partial collection of simple rtti, which are only suggested by Mr. Stroustrup to Rtti connotation. I believe that in the near future, the rtti, will be provided by the C + + compiler, but when will this standard be set? Nobody knows!
Rtti provided by the programmer himself
Usually the programmer himself can provide a simple rtti, such as providing the name or identification of a class (TypeID). The most common approach is to define virtual functions such as Type_na () and ISA () functions for the class system. Let's take a look at an example:
Class Figure {};
Class Rectangle:public Figure {};
Class Square:public Rectangle
{int data;
Public
Square () {data=88;}
void Display () {cout << data << Endl;}
};
void Main ()
{Figure *f = new Rectangle ();
Square *s = (square *) F;
S-and Display ();
}
When s points to the object of rectangle, and S->display () calls Square::D isplay (), the data value will not be found. If the RTTI can be used to check the execution, an error message can be sent. Then, add the Rtti function by yourself:
Class Figure
{public:
Virtual char* Type_na () {return "figure";}
virtual int Isa (char* cna) {return!strcmp (CNA, "figure")? 1:0;}
};
Class Rectangle:public Figure
{public:
Virtual char* Type_na () {return "Rectangle";}
virtual int Isa (char* cna) {return!strcmp (CNA, "Rectangle")? 1:figure::isa (CNA);}
Static rectangle* dynamic_cast (figure* FG) {return FG, ISA (Type_na ())? ( rectangle*) fg:0; }
};
Class Square:public Rectangle
{int data;
Public
Square () {data=88;}
Virtual char* Type_na () {return "Square";}
virtual int Isa (char* cna) {return!strcmp (CNA, "Rectangle")? 1:rectangle::isa (CNA);}
Static square* dynamic_cast (Figure *FG) {return Fg->isa (Type_na ())? (square*) fg:0; }
void Display () {cout << "888" << endl;}
};
The virtual function Type_na () provides the rtti, of the class name and ISA () provides inheritance rtti, to support the dynamic turn type function ──dynamic_cast (). For example
Figure *f = new Rectangle ();
cout << F, Isa ("Square") << Endl;
cout << F, Isa ("figure") << Endl;
These directives show that the object that:f points to is not the object of square, but the object of the figure (including descendants). Again such as:
Figure *f; Square *s;
f = new Rectangle ();
s = Square = = dynamic_cast (f);
if (!s)
cout << "dynamic_cast error!!" << Endl;
At this point, according to Rtti to determine the type of the turn is wrong.
Class Library provides Rtti
It is most common to provide rtti by class libraries, such as the MFC class Library of Visual C + +, which has a CRuntimeClass class that contains simple rtti. Take a look at the program:
Class Figure:public CObject
{
Declare_dynamic (figure);
};
Class Rectangle:public Figure
{
Declare_dynamic (Rectangle);
};
Class Square:public Rectangle
{
Declare_dynamic (Square);
int data;
Public
void Display () {cout << data << Endl;}
Square () {data=88;}
};
Implement_dynamic (figure, CObject);
Implement_dynamic (Rectangle, figure);
Implement_dynamic (Square, Rectangle);
Visual C + + programs rely on these macros (MACOR) to support Rtti. Now let's see how to use the CRuntimeClass Class! as follows:
CRuntimeClass *r;
Figure *f = new Rectangle ();
R = f-Getruntimeclass ();
cout << R-M_psclassname << Endl;
This gets the name of the class at execution time. The Visual C + + class library provides only simpler rtti── class names, object sizes, and parent classes. Other commonly used rtti such as the type and location of data items (position) are not available.
The C + + compiler provides RTTI
It is most convenient to provide rtti directly from the C + + language, but because the scope of rtti varies with the application, if the C + + language provides all the rtti, will greatly increase the complexity of C + +. Currently the,c++ language only provides simple rtti, such as Borland C + + new typeID () operands and dynamic_cast<t*> function samples. Take a look at the program:
Class Figure
{public:
virtual void Display ();
};
Class Rectangle:public Figure {};
Class Square:public Rectangle
{int data;
Public
Square () {data=88;}
void Display () {cout << data << Endl;}
};
Now look at how to use the typeID () operand
Figure *f = new Square ();
Const TypeInfo ty = typeid (*f);
cout << ty.name () << Endl;
This tells you the object that the:f pointer refers to, and its class name is square. And then look at how to use the Dynamic_cast<t*> function sample version
Figure *f; Square *s;
f = new Rectangle ();
s = Dynamic_cast<sqiare *> (f);
if (!s)
cout << "Dynamic casting error!!" << Endl;
When executed, it is found that F cannot be converted to square * type. The following directives:
Figure *f; Rectangle *r;
f = new Square ();
r = Dynamic_cast<rectangle *> (f);
if (r) R->display ();
This type conversion is the right one.
Rtti and virtual function table
In a C + + program, if the class contains virtual functions, the class will have a virtual function table (virtual functions table, abbreviated VFT). In order to provide rtti,c++, a pointer will be appended to the VFT, pointing to the TypeInfo object, which contains rtti data.
Because each object of this class is instantiated, it contains a pointer pointing to the VFT table, so that each object can be removed TypeInfo object and get Rtti. For example
Figure *f1 = new Square ();
Figure *f2 = new Square ();
Const TypeInfo ty = typeid (*F2);
The actions of,typeid (*F2) are:
1. Obtain the object referred to by F2.
2. Remove the pointer from the object pointing to the VMF and obtain the VFT table by this pointer.
3. Find the pointer to the TypeInfo object from the table and get the TypeInfo object by this pointer.
This TypeInfo object will contain Rtti. TypeInfo objects can be obtained through the F1 and F2 two pointers, so typeid (*f2) = = typeID (*F1).
Summary
Rtti is a new feature of C + +. When,c++ languages were used to provide rtti, most of them relied on class libraries to support them, but the methods used in different libraries made the program portability (portability) greatly affected. However, at present, C + + only provides the simplest rtti, the foreseeable future, when everyone's opinions on rtti become consistent,c++ will provide more complete rtti, including data items and member functions of the type, location (offset) and other information, so that C + + programs more orderly, easy to maintain.
Resources
[Note 1] Stroustrup B., "Run-time Type identification for C + +", Usenix C + + C
Onference, Portland, 1993.
[Note 2] Meyer b.,object-oriented Software Construction, Prentice Hall, 1988
Http://www.cnblogs.com/yc_sunniwell/archive/2010/07/07/1773068.html
RTTI concepts and Uses of C + + (very detailed)