Package list
lintian-fixes/upstream

## identity.hh @lintian-fixes/upstream — raw · history · blame

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 #ifndef __LOUT_OBJECTX_HH__ #define __LOUT_OBJECTX_HH__ #include "object.hh" #include "container.hh" #include "signal.hh" namespace lout { /** * \brief Some stuff to identify classes of objects at run-time. */ namespace identity { /** * \brief Instances of classes, which are sub classes of this class, may * be identified at run-time. * *

Testing the class

* * Since e.g. dw::Textblock is a sub class of IdentifiableObject, and * implemented in the correct way (as described below), for any given * IdentifiableObject the following test can be done: * * \code * identity::IdentifiableObject *o; * // ... * bool isATextblock = o->instanceOf(dw::Textblock::CLASS_ID); * \endcode * * \em isATextblock is true, when \em o is an instance of dw::Textblock, * or of a sub class of dw::Textblock. Otherwise, \em isATextblock is false. * * It is also possible to get the class identifier of an * identity::IdentifiableObject, e.g. * * \code * bool isOnlyATextblock = o->getClassId() == dw::Textblock::CLASS_ID; * \endcode * * would result in true, if o is an instance of dw::Textblock, but not an * instance of a sub class of dw::Textblock. * *

Defining Sub Classes

* * Each direct or indirect sub class of IdentifiableObject must * *
*
• add a static int CLASS_ID with -1 as initial value, and *
• call registerName (\em name, &CLASS_ID) in the constructor, where * \em name should be unique, e.g. the fully qualified class name. *
* * After this, class::CLASS_ID refers to a number, which denotes the * class. (If this is still -1, since the class has not yet been instantiated, * any test will fail, which is correct.) * *

Notes on implementation

* * If there are some classes like this: * * \dot * digraph G { * node [shape=record, fontname=Helvetica, fontsize=10]; * edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica, * labelfontsize=10, color="#404040", labelfontcolor="#000080"]; * fontname=Helvetica; fontsize=10; * IdentifiableObject [color="#a0a0a0"]; * A; * B [color="#a0a0a0"]; * C; * IdentifiableObject -> A; * IdentifiableObject -> B; * B -> C; * } * \enddot * *
[\ref uml-legend "legend"]
* * and first, an instance of A, and then an instance of C is created, there * will be the following calls of functions and constructors: * *
*
1. %IdentifiableObject (); *
2. %registerName ("A", &A::CLASS_ID); *
3. %IdentifiableObject (); *
4. %registerName ("B", &B::CLASS_ID); *
5. %registerName ("C", &C::CLASS_ID); *
* * From this, the class hierarchy above can easily constructed, and stored * in identity::IdentifiableObject::classesByName and * in identity::IdentifiableObject::classesById. See the code for details. * * N.b. Multiple inheritance is not supported, the construction of the * tree would become confused. */ class IdentifiableObject: public object::Object { private: class Class: public object::Object { public: Class *parent; int id; const char *className; Class (Class *parent, int id, const char *className); }; static container::typed::HashTable *classesByName; static container::typed::Vector *classesById; static Class *currentlyConstructedClass; int classId; protected: void registerName (const char *className, int *classId); public: IdentifiableObject (); virtual void intoStringBuffer(misc::StringBuffer *sb); /** * \brief Returns the class identifier. * * This is rarely used, rather, tests with * identity::IdentifiableObject::instanceOf are done. */ int getClassId () { return classId; } /** * \brief Return the name, under which the class of this object was * registered. */ const char *getClassName() { return classesById->get(classId)->className; } bool instanceOf (int otherClassId); }; } // namespace identity } // namespace lout #endif // __LOUT_OBJECTX_HH__