ObjectARX运行时类信息实现原理

新公司维护基于CAD的二次开发旧代码。学习ObjectARX相关的内容。

先看原始代码

class MyClass: public AcRxObject
{
public:
	virtual AcRxClass* isA() const
	{
		if (MyClass::gpDesc != NULL)
			return MyClass::gpDesc; 
		return MyClass::gpDesc
        = (AcRxClass*)((AcRxDictionary*)acrxSysRegistry()
			->at(ACRX_CLASS_DICTIONARY))->at(ACRX_T(#MyClass));
	}
    static AcRxClass* gpDesc;
    static AcRxClass* desc()
	{
		if (MyClass::gpDesc != NULL)
			return MyClass::gpDesc;
		return MyClass::gpDesc = (AcRxClass*)((AcRxDictionary*)acrxSysRegistry()
        ->at(ACRX_CLASS_DICTIONARY))->at( ACRX_T(#MyClass) );
	}
    static MyClass* cast(const AcRxObject* inPtr)
    { 
		return ((inPtr == NULL) || !inPtr->isKindOf(MyClass::desc()))
          ? NULL : (MyClass*)inPtr; 
	}
#if 0 	//第一套方案
    static void rxInit()
	{    
		if (MyClass::gpDesc) 
		{
			AcRxClass *pClass =
			(AcRxClass*)((AcRxDictionary*)acrxSysRegistry()
				->at(ACRX_CLASS_DICTIONARY))->at(ACRX_T(#MyClass));
			if (pClass) 
			{
				if (MyClass::gpDesc == pClass)
					return;
				else
					acrx_abort(ACRX_T(/*MSGO*/"Class mismatch"));
			}
		}
		MyClass::gpDesc = 
			newAcRxClass(ACRX_T(#MyClass), ACRX_T(#MyClass));
	}
    static void rxInit(AppNameChangeFuncPtr);
	
#else
	
	static AcRxObject * make##MyClass() { return new MyClass(); } \
	void rxInit() 
	{
		
		if (MyClass::gpDesc) 
		{
			AcRxClass *pClass =
			(AcRxClass*)((AcRxDictionary*)acrxSysRegistry()
				->at(ACRX_CLASS_DICTIONARY))->at(ACRX_T(#MyClass));
			if (pClass) 
			{
				if (MyClass::gpDesc == pClass)
					return;
				else
					acrx_abort(ACRX_T(/*MSGO*/"Class mismatch"));
			}
		}
		MyClass::gpDesc = newAcRxClass(ACRX_T(#MyClass), ACRX_T(#PARENT_CLASS),
        VERNO, &make##MyClass);
	}

#endif

static AcRxObject * make##MyClass() { return new MyClass(); }
void MyClass::rxInit() 
{
	ACRX_STATIC_CHECK(MyClass);
	MyClass::gpDesc = newAcRxClass(ACRX_T(#MyClass), ACRX_T(#PARENT_CLASS),
		DWG_VERSION,MAINTENANCE_VERSION,PROXY_FLAGS, 
		&make##MyClass, ACRX_T(#DXF_NAME), ACRX_T(#APP));
}
void MyClass::rxInit(AppNameChangeFuncPtr ptr) {
	ACRX_STATIC_CHECK(MyClass);
	MyClass::gpDesc = newAcRxClass(ACRX_T(#MyClass), ACRX_T(#PARENT_CLASS),
	DWG_VERSION,MAINTENANCE_VERSION,PROXY_FLAGS, 
	&make##MyClass, ACRX_T(#DXF_NAME), ACRX_T(#APP), ptr);
}

	
};	
AcRxClass* MyClass::gpDesc = NULL;

inline bool AcRxObject::isKindOf(const AcRxClass* pOtherClass) const
{
    const AcRxClass * pMyClass = this->isA();
    return pMyClass == NULL ? false : pMyClass->isDerivedFrom(pOtherClass);

}
void test( )
{
  AcDbEntity *pEnt...;
  if(pEnt->isA()==AcDbLine::desc())
  {
	  //实体正好是一条线段
  }



 if(pEnt->isKindOf(AcDbLine::desc()) 
 {
	 AcDbLine* pLine = AcDbLine::cast(pEnt); 
	 //要判断实体是线段或者线段的派生对象
 }

}

实现原理:

AcRxObject类及其派生类的静态成员gpDesc(AcRxClass类型)存储了运行时信息,在加载过程中完成初始化,同时会将此类注册到ObjectARX也会加入到系统的acrxClassDictionary中。

AcRxObject中相关的成员函数:

desc(),static,返回AcRxObject类(及其派生类)的运行时类信息描述符(对象);

cast(),static,返回指定对象的运行时类信息对象,如果不是这个类(或其子类),返回NULL;

isKindOf (),判断指定对象是否属于这个类(或其派生类);

isA(),返回对象自己的运行时类信息描述符。

 

=============================================
AcRxClass是 AcRxObject类(及其派生类)的运行时类信息类。
AcRxClass保存了当前类及其父类的关系等相关数据
AcRxObject::isA 和AcRxObject::desc功能类似。
前者是多态性体现着,后者是类的静态数据(绝对).
前者用于动态创建的对象,后者用于得到具体类类型信息.
cast用于进行具体转换。
kindof调用isA,再从类型信息树中递归查询信息。
注意:cast中调用了isKindOf 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ObjectARX 是 AutoCAD 的编程接口,可以使用 C++ 编程语言来扩展 AutoCAD 的功能。要实现对称函数,可以使用 ObjectARX 提供的实体对象 AcDbEntity 和 AcDbMirrorEntityPE 。 首先,创建一个派生自 AcDbEntity 的实体,例如 MyEntity。然后在 MyEntity 中重载 AcDbEntity 的 mirror() 函数,实现对称的操作。mirror() 函数的定义如下: ``` virtual Acad::ErrorStatus mirror(const AcGePlane& plane, AcDbObject*& pMirrorObj) override; ``` 在 mirror() 函数中,可以使用 AcDbMirrorEntityPE 的成员函数 mirror() 来实现对称操作。mirror() 函数的定义如下: ``` virtual Acad::ErrorStatus mirror(AcDbEntity* pEnt, const AcGePlane& plane) override; ``` 其中,pEnt 是需要对称的实体对象指针,plane 是对称的平面。mirror() 函数将对称后的实体对象保存在 pMirrorObj 中,并返回 Acad::eOk 表示操作成功。 下面是一个简单的示例代码: ``` class MyEntity : public AcDbEntity { public: ACDB_DECLARE_MEMBERS(MyEntity); virtual Acad::ErrorStatus mirror(const AcGePlane& plane, AcDbObject*& pMirrorObj) override { AcDbMirrorEntityPE* pMirrorPE = AcDbMirrorEntityPE::cast(this); if (pMirrorPE == nullptr) return Acad::eNotImplementedYet; AcDbEntity* pMirrorEnt = nullptr; Acad::ErrorStatus es = pMirrorPE->mirror(this, plane, pMirrorEnt); if (es != Acad::eOk) return es; pMirrorObj = pMirrorEnt; return Acad::eOk; } }; ACDB_REGISTER_OBJECT_ENTRY_AUTO(MyEntity) ``` 在上面的示例中,MyEntity 派生自 AcDbEntity,重载了 mirror() 函数。在 mirror() 函数中,首先使用 AcDbMirrorEntityPE::cast() 函数获取 AcDbMirrorEntityPE 的指针。如果获取失败,说明当前实体对象不支持对称操作,返回 Acad::eNotImplementedYet。否则,调用 pMirrorPE->mirror() 函数实现对称操作,将对称后的实体对象保存在 pMirrorEnt 中,并将 pMirrorEnt 的指针保存在 pMirrorObj 中,最后返回 Acad::eOk 表示操作成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值