The last operation to be implemented is run-time object creation. As described, this operation creates an object of a type specified at run-time by a typeid. In a certain sense, it can be seen as a run-time equivalent of the C++ new operator.
The macro TYPE_NEW which implements run-time object creation needs two parameters. One of them is a typeid t for the type T we want to instantiate. The other one is a C++ class name of a base class B of T. The second parameter is necessary since we have to return the newly created object as a typed object. In other words, TYPE_NEW(B,T) will create a new T and return it as a B*.
The implementation of the TYPE_NEW RTTI operation which performs this task has to add one extra piece of information. Namely, the RTTI system has to maintain a repository of all application classes (more exactly, of all Type_infos of all application classes). When a TYPE_NEW operation is requested, the type to be instantiated is looked up in this repository and, if found, is instantiated.
The proposed solution is to implement this repository in a 'distributed' fashion. Rather than keeping a centralized list of all types of an application, the idea is to let each Type_info know about all types directly derived from it (similarly to the way a Type_info knows about its bases)(Figure 6). This solution fits well the previous description of the TYPE_NEW operation: when TYPE_NEW(T,t) is invoked, the typeid t will be searched in the inheritance graph rooted at T downwards
Figure 6: Type_info implementation support for run-time object creation
Keeping information about derived types inside each Type_info object offers a faster way to locate the existence of a type to be instantiated at run-time than the centralized repository version. Indeed, in the case the information about subclasses is kept locally in each Type_info, the system must only scan the inheritance path starting at the root type specified in the TYPE_NEW operation. If the system kept a 'flat' list with all Type_infos of an application, the worst case search would mean traversing the whole list.
After finding the right Type_info, the system should create a new instance
of its corresponding C++ class. In ordr to do this, it has to call the
C++ new operator passing the C++ class as argument. This can not
be done generically for the same reason which forbade us casting C++ pointers
generically, namely the lack of 'real' type variables in C++. Moreover,
we can't use virtual constructors since the C++ classes the RTTI system
should manage do not always have a common base. The only available solution
is to declare a static method in each C++ application class which returns
a new object of that type. However this is only half of the solution since
we should return the new object as a pointer cast to the typeid argument
supplied to TYPE_NEW. The solution is to use the method
introduced in Section 5.2.5 on
the newly created object, passing it the typeid to cast to.
Figure 7: Example of run-time object creation
In the example presented in Figure 7,
class B inherits from A. The steps of the user request to create a B and
return in as an A* are outlined. First, the Type_info for B is searched
in the graph rooted at A (by a method of Type_info called create()).
When this Type_info is found, the creation static method of class B (i.e.
B::RTTI_new())is retrieved from the Type_info. This implies that a Type_info
for a class has to store a pointer (called here )
to the object creation method RTTI_new of the class it represents. When
this method is called, a B is allocated on the heap and it is returned
as a pointer cast to the typeid of A. Finally, TYPE_NEW will properly cast
the void* returned by
to an A* (which is safe since RTTI_cast produced an A*).
Marginal cases include trying to instantiate non-existing classes (in
which case
will fail to find the respective Type_info and will return NULL) or trying
to instantiate classes which have no default constructors like abstract
classes (in which case the respective Type_info will have a NULL
member so will simply return NULL when asked to instantiate its class).