Defining and Using Smart Pointers
Base Classes
You can declare smart pointers to any of the classes that publicly derive from IlsRefCounted. This class manages reference counting.
The class IlsRefCounted is the base class for IlsEntity and IlsObject, which are in turn base classes for all Server object types.
Thus, you can declare smart pointers to any Server object types.
Base Classes for Server Objects
Classes IlsEntity, IlsObject, and IlsRefCounted are fully documented in the Server Reference Manual.
Defining Smart Pointers
To define smart pointers to an arbitrary class A, you can instantiate the class template , as follows:
typedef IlsSmartPointer<A> AP;
AP designates the class “smart pointers to A”. The name AP is an alias for an instance of the IlsSmartPointer template to class A. Once a smart pointer to a class has been defined, you can use its alias each time you need to manipulate a smart pointer to this class.
Note
The notation we use to name a smart pointer to a class of objects, that is, a P appended to the name of the class, is a user-defined notation, and as such is not |
Class A does not need to be visible when the smart pointer is declared; a forward declaration is necessary and sufficient. Actually, A can be either a class or a struct.
class A;
typedef IlsSmartPointer<A> AP;
class A:
public IlsObject
{
};
Using Smart Pointers
With smart pointers, destructors are set off at logical moments, corresponding to a natural extension of conventional C++ rules. C++ destroys an object under two conditions:
-
Whenever the object is no longer visible within its scope (for example, at the end of its declaration block).
-
Whenever the object is no longer visible from its process (for example when the main function returns).
Similarly, smart pointers trigger the deletion of an object allocated by new as soon as this object is no longer visible from the stack or from any smart pointer (stored in variables or declared as an object data member).
Consider class Screen and its associated smart pointer ScreenP:
{
ScreenP ss=new Screen();
..
}
// The screen gets deleted
When the block is left, if the object created is visible only to ss, then the object destructor is called.
When you use a smart pointer to an object, you must not explicitly delete the object. If you do so, you might violate data integrity.
You must not create smart pointers to objects that have not been allocated by new —for example, objects on the stack, global objects, objects nested in other objects. Also, you must not create smart pointers to objects whose destructor is already in the call stack. Doing so, you would, among other things, destroy the same object twice.
Dereferencing a null smart pointer throws the IlsNullPointerDereferencing exception. For details about exceptions, see Exception Handling.
Some compilers do not implement separate compilation of templates. Thus, it is sometimes necessary to put the definition of a class A in compilation units containing the smart pointer definition.
Warning It is not possible to pass a smart pointer to A to a function that expects a smart pointer to B, base class of A. In practice, to carry out such a conversion, the compiler would first have to convert the smart pointer to A to an ordinary pointer to A (a user-defined conversion) and then to carry out an implicit conversion from A* to B*. Then, it would have to build a smart pointer to B, starting from B*, and that, too, counts as a supplementary user-defined conversion. C++ can implicitly carry out one user-defined conversion at most. In such a case, to “help out’’ the compiler, you must use the member function getValue of the smart pointer to eliminate that first user-defined conversion. For details about this function, see the Server Reference Manual. Also, for some compilers, converting the constant 0 to a smart pointer requires two user-defined conversions: the first one to convert 0 to a pointer type, the second one to convert the pointer to the smart pointer. In this case, you have to “help” the compiler by casting the constant 0 to the pointer type. If tp is a smart pointer to T, you have to write tp=(T*)0; to be able to compile. |