ObjectARX Reference Guide > AcDb Classes > AcDbObject Class
AcDbObject
Class Hierarchy
C++
class AcDbObject : public AcGiDrawable, public AcHeapOperators;
File

dbmain.h

Description

The AcDbObject class is the base class for all objects that reside in an AcDbDatabase object. This class provides all the functionality for database residency such as objectId, handle, ownership backpointer, filing, persistent reactor notification, xdata, deepClone, object state queries, erase, audit, etc. Many of these involve virtual functions so that they can be overridden in classes derived from AcDbObject.

Construction / Deletion

When you wish to add an object to an AcDbDatabase, you must allocate it via new(), never by declaring it directly on the stack. Once an object is added to an AcDbDatabase object, whether directly (that is, via AcDbDatabase::addAcDbObject())or indirectly (that is, adding it to an AcDbBlockTableRecord or AcDbDictionary object), responsibility of deleting the object lies with the AcDbDatabase object. No form of Undo or Cancel overrides this! To remove an object from a database, use AcDbObject::erase() to mark it as erased so that it is not filed out during any subsequent saves. 

Relying on other AcDbObject instances during construction or deletion is prohibited, and likely to end in program failure. 

Objects needing to free up objects from other object chains, such as non-persistent reactors, are advised to

  1. reconsider using persistent reactors, and
  2. override their AcDbObject::goodbye() member to do cleanup.
For a given database, all objects have their goodbye() members invoked before all objects are subsequently deleted in an arbitrary order. Relying on order of AcDbObject deletion at drawing close time is not considered a healthy, or supportable, practice. Beware that when xrefs are present, the databases are deleted in sequence. So, inter-xref references can be unpredictably broken unless the references set up callbacks to AcDbObjectReactor::goodbye(), and listen for each other's goodbyes.

Access

Never access a pointer to an object that is closed.

Opening Objects

Objects can be opened in one of three modes: 

 

Value 
Meaning 
AcDb::kForRead 
Up to 256 readers can be opened at once, as long as object is not already open kForWrite or kForNotify. Member functions invoked when an object is opened kForRead should not cause object to be modified. 
AcDb::kForWrite 
Can be opened for write if it is not open at all, otherwise an open kForWrite fails. Member functions invoked when an object is opened kForWrite may or may not modify the object. 
AcDb::kForNotify 
Can be opened for notification whenever it is closed, open for read (any number) or open for write, but not when it is already open for notify. Member functions allowed to be invoked when open in this mode should not interfere with any current readers or writers, although they may cause the object to alter itself. 

 

kForNotify is intended to be the most powerful open function, and the most transient. Opening in kForNotify mode can only fail if a previous user has left it open in this mode. When open in this mode, any subsequent open requests fail, even kForNotify. Therefore, this mode should be used sparingly, and objects opened in this mode should be sent the proper member function call or calls and closed as soon as possible. 

Because of the restrictions on multiple opening of objects, never leave objects open any longer than necessary and always try to open in the least restrictive mode necessary.

Implementation

Definitions of member functions in custom classes derived from AcDbObject should begin with a call to one of the following AcDbObject methods in order to be sure the object is opened in the correct mode and to prime or trigger the notification mechanism (if appropriate): 

Classes that derive from AcDbObject and then use dllexport() on that class will need to add their own new[] and delete[] operators. 

Remarks

  • When objects that either point to or refer to other objects via objectId are first created, and have not been added to a database yet, their capability is often diminished without extra calls to some custom initialization routines, as some of their fields only take on legitimate meaning after being added to a database. AcDbObject programmers can always cover this, but it is always extra work, so be sure to test your operations on non-database-resident objects at least as thoroughly as your operations on database-resident objects.
  • When you are trying to do a persistence mechanism, if you know the class of the object, a default instance of it can constructed via ::desc()->create(), then given an appropriate filer with which to construct itself.
  • In usage and appearance, object extension dictionaries look like normal instances of AcDbDictionary, and even have the same DXF representation, using 350 (soft ownership ID) group codes for their owned objects. However, internally they are treated as hard owners of their entries, not soft owners, for purposes of PURGE and WBLOCK.
  • The clone() and copyFrom() methods are introduced in AcRxObject, where they are virtual. However the AcDbObject implementations make use of dwgIn() and dwgOut(), passing in an eCopyFiler. Although it would be possible to prevent a clone of a custom entity from occurring by overriding the clone() and copyFrom() methods, the correct way to accomplish this is to disable the clone from within the dwgInFields() and dwgOutFields() methods, based on the type of filer that is passed in.
  • If you do not want a custom object to be deepCloned for any reason, you need to override AcDbObject::deepClone() and AcDbObject::wblockClone() for the custom entity. Have them set the pClonedObject argument to NULL and return Acad::eOk.
  • To prevent deepClone() and wblockClone() when the object is a proxy, you'll need to make sure the AcDbProxyObject::kCloningAllowed or AcDbProxyEntity::kCloningAllowed bit is not set in the proxyFlags argument of the ACRX_DXF_DEFINE_MEMBERS macro call you make in your class definition code.

Links
See Also