Table of Contents

定义数据对象类

XT中数据对象均从XItem继承而来,任何数据对象都有类型标识,身份ID,其中类型标识用于和其他对象区分,对外部访问而言,以字符串标识(通过静态函数ctypeString()访问,字符串长度应小于16),对于内部使用(运行时),则使用整数标识(在注册时动态生成,通过静态函数ctype()访问);整数身份ID(通过getId()访问),管理类通过身份ID构建对象的索引。

默认情况下,数据对象的整数标识按照注册顺序,从类型标识基数开始递增,类型标识基数与管理器的整数标识存在如下关系:

ItemTypeBase = DomainType*DomainItemTypeSize

其中DomainType为管理器整数标识,DomainItemTypeSize为每个管理器能容纳的对象类型的最大数目(现设为10000)。 开发者也可以为数据对象指定固定的整数标识,该整数标识须在(ItemTypeBase,ItemTypeBase+DomainItemTypeSize)区间。

下面是最简单的数据对象类声明和类实现:

//header
class XT_EXT_DOMAIN TestItem : public XItem
{
DECLARE_CITEM(TestItem)
public:
TestItem (ulong id);
~TestItem ();
}

//cpp
REGISTER_CITEM(TestItem, "CTESTITEM", TestManager::ctype(), 0);
TestItem::TestItem(ulong id)
:XItem(id,TestItem::ctype())
{	
}

其中宏DECLARE_CITEM用于声明类型标识接口,宏REGISTER_CITEM用于实现类型标识接口,在对象构造函数中显示调用TestItem::ctype()以指定该对象的运行时类型,id一般由该对象的管理器自动分配。

宏REGISTER_CITEM的完整形式如下:

REGISTER_CITEM(ITEM, typeSTR, domainTYPE, typeID)

其中ITEM是数据类,typeSTR是类型字符串标识,typeID是整数标识,typeSTR不得与已注册的字符串重复并且字符串长度须小于16;domainTYPE为该数据对象所属的管理器的整数类型标识,必须在管理器注册后才能使用;当需要为ITEM自动获取类型ID时,将typeID设置为0即可,否则将按照typeID的值赋给ITEM。 一般的,类型字符串typeSTR格式可参考给定C[UserCode][DomainCode][ClassName],以大写字母C开头(Class),其中UserCode为3个字母的用户缩写码,在用户定制的场合使用,是可选项;DomainCode为3个字母的缩写域码,用于表示它所属的域类型,是可选项;ClassName是能表达数据对象类型的有意义的字符串,整体长度应小于16个字符,

带名字的数据对象

对于带有名字的数据对象,可以从NItem继承实现。NItem提供了setName和getName的接口用于设置和获取数据对象的名字。数据对象的名字最长不得超过64个字符。

有从属关系的数据对象

如果数据对象A至多属于一个数据对象B,则定义数据对象A和B具有从属关系。如几何面由三角片单元集组成,每一个三角片单元至多属于一个几何面。具有从属关系的数据对象来说,从对象在主对象中保持着顺序(一般是从对象加入主对象的顺序),从对象从OrderItem(当对象没有Name属性时)或者NOrderItem继承而来(当对象有Name属性时)。 当定义有从属关系的数据对象时,首先定义从对象:

class MasterItem;
class SlaveItem : public NOrderItem
{
private:
  const MasterItem* m_pMaster;
  DECLARE_CITEM(SlaveItem )
public:
  SlaveItem (ulong id);
  const MasterItem* getMaster() const { return m_pMaster; }
  void setMaster(const MasterItem* master) { m_pMaster= master; }
};

然后,定义主对象,主对象中需要声明首尾从对象的指针,并且要实现attach和detach从对象的接口:

class MasterItem : public NItem
{
  friend class SlaveManager;
  const SlaveItem * m_pFront = 0, *m_pBack = 0;
  ulong m_ulCount;
  DECLARE_CITEM(MasterItem )
public:
  MasterItem (ulong id) :NItem(id, MasterItem ::ctype()) { ; }
  void attach(SlaveItem * pElement, SlaveManager* elMgr);
  void detach(SlaveItem * pElement, SlaveManager* elMgr);
  const SlaveItem * getFirstScene() const { return m_pFront; }
};

其中attach实现逻辑如下:

void MasterItem ::attach(SlaveItem* pElement, SlaveManager* elMgr)
{
  assert(pElement->getMaster() != this);
  if (m_pFront == NULL) {
    m_pFront = pElement;
    m_pBack = pElement;
    pElement->setNext(NULL);
    pElement->setPrev(NULL);
  }
  else {
    elMgr->checkOutPrevNextItem(m_pBack)->setNext(pElement);
    pElement->setNext(NULL);
    pElement->setPrev(m_pBack);
    m_pBack = pElement;
  }
  pElement->setMaster((MasterItem*)this);
  ++m_ulCount;
}