- Timestamp:
- Dec 1, 2007, 4:24:56 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/objecthierarchy/src/orxonox/core/Identifier.h
r362 r365 1 /*! 2 @file Identifier.h 3 @brief Definition of the Identifier, ClassIdentifier and SubclassIdentifier classes. 4 5 The Identifier contains all needed informations about the class it belongs to: 6 - the name 7 - a list with all objects 8 - parents and childs 9 - the factory, if available 10 - the networkID that can be synchronised with the server 11 12 Every object has a pointer to the Identifier of its class. This allows the use isA(...), 13 isDirectlyA(...), isChildOf(...) and isParentOf(...). 14 15 To create the class-hierarchy, the Identifier has some intern functions and variables. 16 17 Every Identifier is in fact a ClassIdentifier, but they are derived from Identifier. 18 19 SubclassIdentifier is a separated class, acting like an Identifier, but has a given class. 20 You can only assign Identifiers of the given class or a derivative to a SubclassIdentifier. 21 */ 22 1 23 #ifndef _Identifier_H__ 2 24 #define _Identifier_H__ … … 13 35 namespace orxonox 14 36 { 15 class BaseObject; 37 class BaseObject; // Forward declaration 16 38 17 39 // ############################### 18 40 // ### Identifier ### 19 41 // ############################### 42 //! The Identifier is used to identify the class of an object and to store informations about the class. 43 /** 44 The Identifier contains all needed informations about the class it belongs to: 45 - the name 46 - a list with all objects 47 - parents and childs 48 - the factory, if available 49 - the networkID that can be synchronised with the server 50 51 Every object has a pointer to the Identifier of its class. This allows the use isA(...), 52 isDirectlyA(...), isChildOf(...) and isParentOf(...). 53 54 You can't directly create an Identifier, it's just the base-class for ClassIdentifier. 55 */ 20 56 class Identifier 21 57 { 22 58 template <class T> 23 friend class ClassIdentifier; 59 friend class ClassIdentifier; // Forward declaration 24 60 25 61 template <class T> 26 friend class SubclassIdentifier; 62 friend class SubclassIdentifier; // Forward declaration 27 63 28 64 template <class T> 29 friend class ClassFactory; 65 friend class ClassFactory; // Forward declaration 30 66 31 67 public: 68 /** @brief Sets the Factory. @param facotry The factory to assign */ 32 69 inline void addFactory(BaseFactory* factory) { this->factory_ = factory; } 70 33 71 BaseObject* fabricate(); 34 72 … … 38 76 bool isParentOf(const Identifier* identifier) const; 39 77 78 /** @returns the name of the class the Identifier belongs to. */ 40 79 inline const std::string& getName() const { return this->name_; } 80 81 /** @returns the parents of the class the Identifier belongs to. */ 41 82 inline const IdentifierList& getParents() const { return this->parents_; } 83 84 /** @returns the children of the class the Identifier belongs to. */ 42 85 inline IdentifierList& getChildren() const { return *this->children_; } 43 86 87 /** @returns true, if a branch of the class-hierarchy is getting created, causing all new objects to store their parents. */ 44 88 inline static bool isCreatingHierarchy() { return (hierarchyCreatingCounter_s > 0); } 45 89 90 /** @returns the NetworkID to identify a class through the network. */ 46 91 inline const unsigned int getNetworkID() const { return this->classID_; } 92 47 93 void setNetworkID(unsigned int id); 48 94 49 95 private: 50 96 Identifier(); 51 Identifier(const Identifier& identifier) {} 97 Identifier(const Identifier& identifier) {} // don't copy 52 98 virtual ~Identifier(); 53 99 void initialize(const IdentifierList* parents); 54 100 101 /** 102 @brief Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents. 103 */ 55 104 inline static void startCreatingHierarchy() 56 105 { … … 61 110 } 62 111 112 /** 113 @brief Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents. 114 */ 63 115 inline static void stopCreatingHierarchy() 64 116 { … … 69 121 } 70 122 71 IdentifierList parents_; 72 IdentifierList* children_; 73 74 std::string name_; 75 76 BaseFactory* factory_; 77 bool bCreatedOneObject_; 78 static int hierarchyCreatingCounter_s; 79 static unsigned int classIDcounter_s; 80 unsigned int classID_; 123 IdentifierList parents_; //!< The Parents of the class the Identifier belongs to 124 IdentifierList* children_; //!< The Children of the class the Identifier belongs to 125 126 std::string name_; //!< The name of the class the Identifier belongs to 127 128 BaseFactory* factory_; //!< The Factory, able to create new objects of the given class 129 bool bCreatedOneObject_; //!< True if at least one object of the given type was created (used to determine the need of storing the parents) 130 static int hierarchyCreatingCounter_s; //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading) 131 static unsigned int classIDcounter_s; //!< The number of unique Identifiers 132 unsigned int classID_; //!< The networkID to identify a class through the network 81 133 }; 82 134 … … 85 137 // ### ClassIdentifier ### 86 138 // ############################### 139 //! The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have. 140 /** 141 ClassIdentifier is a Singleton, which means that only one object of a given type T exists. 142 This makes it possible to store informations about a class, sharing them with all 143 objects of that class without defining static variables in every class. 144 */ 87 145 template <class T> 88 146 class ClassIdentifier : public Identifier … … 95 153 private: 96 154 ClassIdentifier(); 97 ClassIdentifier(const ClassIdentifier<T>& identifier) {} 155 ClassIdentifier(const ClassIdentifier<T>& identifier) {} // don't copy 98 156 ~ClassIdentifier(); 99 157 100 static ClassIdentifier<T>* pointer_s; 101 ObjectList<T>* objects_; 158 static ClassIdentifier<T>* pointer_s; //!< A pointer to the singleton-object 159 ObjectList<T>* objects_; //!< The ObjectList, containing all objects of type T 102 160 }; 103 161 104 162 template <class T> 105 ClassIdentifier<T>* ClassIdentifier<T>::pointer_s = NULL; 106 163 ClassIdentifier<T>* ClassIdentifier<T>::pointer_s = NULL; // Set the static member variable pointer_s to zero 164 165 /** 166 @brief Constructor: Create the ObjectList. 167 */ 107 168 template <class T> 108 169 ClassIdentifier<T>::ClassIdentifier() … … 111 172 } 112 173 174 /** 175 @brief Destructor: Delete the ObjectList, set the singleton-pointer to zero. 176 */ 113 177 template <class T> 114 178 ClassIdentifier<T>::~ClassIdentifier() … … 118 182 } 119 183 184 /** 185 @brief Registers a class, which means that the name and the parents get stored. 186 @param parents An IdentifierList, containing the Identifiers of all parents of the class 187 @param name A string, containing exactly the name of the class 188 @param bRootClass True if the class is either an Interface or BaseObject itself 189 @return The ClassIdentifier itself 190 */ 120 191 template <class T> 121 192 ClassIdentifier<T>* ClassIdentifier<T>::registerClass(const IdentifierList* parents, const std::string& name, bool bRootClass) … … 124 195 std::cout << "*** Register Class in " << name << "-Singleton.\n"; 125 196 #endif 197 198 // It's a singleton, so maybe we have to create it first 126 199 if (!pointer_s) 127 200 { … … 132 205 } 133 206 207 // Check if at least one object of the given type was created 134 208 if (!pointer_s->bCreatedOneObject_) 135 209 { 210 // If no: We have to store the informations and initialize the Identifier 211 136 212 #if HIERARCHY_VERBOSE 137 213 std::cout << "*** Register Class in " << name << "-Singleton -> Initialize Singleton.\n"; 138 214 #endif 139 215 pointer_s->name_ = name; 140 Factory::add(name, pointer_s); 216 Factory::add(name, pointer_s); // Add the Identifier to the Factory 141 217 142 218 if (bRootClass) 143 pointer_s->initialize(NULL); 219 pointer_s->initialize(NULL); // If a class is derived from two interfaces, the second interface might think it's derived from the first because of the order of constructor-calls. Thats why we set parents to zero in that case. 144 220 else 145 221 pointer_s->initialize(parents); … … 149 225 } 150 226 227 /** 228 @returns the Identifier itself 229 */ 151 230 template <class T> 152 231 ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier() … … 163 242 } 164 243 244 /** 245 @brief Adds an object of the given type to the ObjectList. 246 @param object The object to add 247 */ 165 248 template <class T> 166 249 void ClassIdentifier<T>::addObject(T* object) … … 169 252 std::cout << "*** Added object to " << ClassIdentifier<T>::getIdentifier()->getName() << "-list.\n"; 170 253 #endif 171 object->getMetaList() ->add(ClassIdentifier<T>::getIdentifier()->objects_, ClassIdentifier<T>::getIdentifier()->objects_->add(object));254 object->getMetaList().add(ClassIdentifier<T>::getIdentifier()->objects_, ClassIdentifier<T>::getIdentifier()->objects_->add(object)); 172 255 } 173 256 … … 176 259 // ### SubclassIdentifier ### 177 260 // ############################### 178 template <class B> 261 //! The SubclassIdentifier acts almost like an Identifier, but has some prerequisites. 262 /** 263 You can only assign Identifiers that belong to a class of at least B (or derived) to a SubclassIdentifier<T>. 264 If you assign something else, the program aborts. 265 Because we know the minimal type, a dynamic_cast is done, which makes it easier to create a new object. 266 */ 267 template <class T> 179 268 class SubclassIdentifier 180 269 { 181 270 public: 182 SubclassIdentifier(); 183 184 SubclassIdentifier<B>& operator=(Identifier* identifier) 185 { 186 if (!identifier->isA(ClassIdentifier<B>::getIdentifier())) 271 /** 272 @brief Constructor: Automaticaly assigns the Identifier of the given class. 273 */ 274 SubclassIdentifier() 275 { 276 this->identifier_ = ClassIdentifier<T>::getIdentifier(); 277 } 278 279 /** 280 @brief Overloading of the = operator: assigns the identifier and checks its type. 281 @param identifier The Identifier to assign 282 @return The SubclassIdentifier itself 283 */ 284 SubclassIdentifier<T>& operator=(Identifier* identifier) 285 { 286 if (!identifier->isA(ClassIdentifier<T>::getIdentifier())) 187 287 { 188 std::cout << "Error: Class " << identifier->getName() << " is not a " << ClassIdentifier< B>::getIdentifier()->getName() << "!\n";189 std::cout << "Error: SubclassIdentifier<" << ClassIdentifier< B>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden.\n";288 std::cout << "Error: Class " << identifier->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!\n"; 289 std::cout << "Error: SubclassIdentifier<" << ClassIdentifier<T>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden.\n"; 190 290 std::cout << "Aborting...\n"; 191 291 abort(); … … 195 295 } 196 296 297 /** 298 @brief Overloading of the * operator: returns the assigned identifier. 299 @return The assigned identifier 300 */ 197 301 Identifier* operator*() 198 302 { … … 200 304 } 201 305 306 /** 307 @brief Overloading of the -> operator: returns the assigned identifier. 308 @return The assigned identifier 309 */ 202 310 Identifier* operator->() const 203 311 { … … 205 313 } 206 314 207 B* fabricate() 315 /** 316 @brief Creates a new object of the type of the assigned identifier and dynamic_casts it to the minimal type given by the SubclassIdentifier. 317 @return The new object 318 */ 319 T* fabricate() 208 320 { 209 321 BaseObject* newObject = this->identifier_->fabricate(); 322 323 // Check if the creation worked 210 324 if (newObject) 211 325 { 212 return dynamic_cast<B*>(newObject); 326 // Do a dynamic_cast, because an object of type T is much better than of type BaseObject 327 return dynamic_cast<T*>(newObject); 213 328 } 214 329 else 215 330 { 331 // Something went terribly wrong 216 332 if (this->identifier_) 217 333 { 218 std::cout << "Error: Class " << this->identifier_->getName() << " is not a " << ClassIdentifier< B>::getIdentifier()->getName() << "!\n";334 std::cout << "Error: Class " << this->identifier_->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << "!\n"; 219 335 std::cout << "Error: Couldn't fabricate a new Object.\n"; 220 336 std::cout << "Aborting...\n"; … … 230 346 } 231 347 348 /** @returns the assigned identifier. */ 232 349 inline const Identifier* getIdentifier() const 233 350 { return this->identifier_; } 351 352 /** @returns true, if the assigned identifier is at least of the given type. @param identifier The identifier to compare with */ 234 353 inline bool isA(const Identifier* identifier) const 235 354 { return this->identifier_->isA(identifier); } 355 356 /** @returns true, if the assigned identifier is exactly of the given type. @param identifier The identifier to compare with */ 236 357 inline bool isDirectlyA(const Identifier* identifier) const 237 358 { return this->identifier_->isDirectlyA(identifier); } 359 360 /** @returns true, if the assigned identifier is a child of the given identifier. @param identifier The identifier to compare with */ 238 361 inline bool isChildOf(const Identifier* identifier) const 239 362 { return this->identifier_->isChildOf(identifier); } 363 364 /** @returns true, if the assigned identifier is a parent of the given identifier. @param identifier The identifier to compare with */ 240 365 inline bool isParentOf(const Identifier* identifier) const 241 366 { return this->identifier_->isParentOf(identifier); } 242 367 243 368 private: 244 Identifier* identifier_; 369 Identifier* identifier_; //!< The assigned identifier 245 370 }; 246 247 template <class B>248 SubclassIdentifier<B>::SubclassIdentifier()249 {250 this->identifier_ = ClassIdentifier<B>::getIdentifier();251 }252 371 } 253 372
Note: See TracChangeset
for help on using the changeset viewer.