Implementation classes and handles
An object of the handle class points to an object of the corresponding implementation class.
Throughout this chapter, it has been taken for granted that the major entities of CP Optimizer are simply objects in the full sense of C++. In fact, CP Optimizer entities depend on two classes: a handle class and an implementation class, where an object of the handle class points to an object of the corresponding implementation class. As documented in the CP Optimizer C++ API Reference Manual, handles are passed by value, and they are created as automatic objects, where “automatic” has the usual C++ meaning.
When using CP Optimizer, you will mostly work with handles, that is, the objects that are really pointers to corresponding implementation objects on the CP Optimizer heap. CP Optimizer takes care of all the allocation, memory-management and de-allocation of these internal implementation objects, keeping the details of these implementation classes “out of sight.” However, if for some reason, you need to define new subclasses of CP Optimizer objects, you need to do so in a two-step process: you'll have to define the underlying implementation class plus the corresponding handle class.
For example, consider the predefined CP Optimizer extensions
class, IlcConstraintI. For this class implementing
an object with its own data members and virtual functions, CP Optimizer
defines the handle class IlcConstraint.
Essentially, such a handle class contains objects that are really
only pointers to instances of the corresponding implementation class IlcConstraintI.
This has the practical effect of elevating the idea of
a pointer to the level of an object itself. A number of advantages
derive from this; for one thing, it provides greater certainty about
how pointers are used. In particular, there is no longer any risk
that the compiler will mistakenly interpret the expression x+1 as
a pointer and apply pointer arithmetic to it. Instead, pointers are
consistently and systematically treated as objects.
However, the fundamental precepts of CP Optimizer that there are “No more pointers” and that “Everything is an object” mean that when you extend CP Optimizer by defining a new implementation class, you must also define a function that returns a handle.