新公司维护基于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