浅谈ObjectARX智能指针AcDbObjectPointer的用法

前言

用ARX智能指针打开对象,可以不在乎是否close,
但同时也要注意这个变量的作用域(生命周期)问题,
ARX智能指针,他的原理是利用类的析构造函数特性自动关闭对象.

这里的智能指针指的是AcDbObjectPointer这一类使用AcDbObjectPointerBase基类派生的类模板统称.

下面是打开示例.

void testOpen()
{
	ads_point pt;
	ads_name ent;
	if (RTNORM != acedEntSel(NULL,ent,pt))
	{
		return;
	}
	AcDbObjectId objId;
	acdbGetObjectId(objId,ent);
	//使用ARX智能指针打开对象,实体类对象可以使用这种方式直接打开.
	AcDbObjectPointer<AcDbBlockReference> pBlkRef(objId,AcDb::kForRead);
	//判断是否打开成功
	//注意ARX智能指针使用智能指针成员函数的时候是点符号"."不是指针符号"->"
	if (Acad::eOk != pBlkRef.openStatus())
	{
		//根据情况做打开失败处理
		acutPrintf(_T("\n打开对象失败!,错误码: %s"),acadErrorStatusText(pBlkRef.openStatus()));
		return;
		//continue;
		//break;
	}
	//打开成功,可以使用对象的指针了注意是指针"->"符号.
	AcGePoint3d ptInsert2 = pBlkRef->position();
	//智能指针打开,close再是必须的处理.
	//close可以多次执行,某些特殊情况,智能指针也需要手动close,所以不会出问题.

	//下面示意创建一个新的对象.
	//先声明pCircle对象
	AcDbObjectPointer<AcDbCircle> pCircle;
	//再创建实体对象,相当于new AcDbCircle
	Acad::ErrorStatus es= pCircle.create();
	//判断是否创建成功
	if (Acad::eOk != es)
	{
		acutPrintf(_T("\n创建对象失败!,错误码: %s"),acadErrorStatusText(es));
		return;
	}
	//设置圆的属性
	pCircle->setCenter(ptInsert2);
	pCircle->setRadius(500.0);

	//下面同样使用智能指针的方式打开模型空间添加实体
	AcDbDatabase *pDb=acdbHostApplicationServices()->workingDatabase();
	//打开块表
	AcDbBlockTablePointer pBlkTbl(pDb,AcDb::kForRead);
	if (Acad::eOk != pBlkTbl.openStatus())
	{
		acutPrintf(_T("\n打开块表失败!,错误码: %s"),acadErrorStatusText(pBlkTbl.openStatus()));
		return;
	}
	//先获取模型空间的ID
	AcDbObjectId mSpaceId;
	pBlkTbl->getAt(ACDB_MODEL_SPACE,mSpaceId);
	//打开块表记录方式一
	AcDbBlockTableRecordPointer pBlkRcd(mSpaceId,AcDb::kForWrite);     //打开块表记录方式二(这种直接用AcDbDatabase参数打开到模型空间块表记录,可以省略打开块表)     //AcDbBlockTableRecordPointer pBlkRcd(ACDB_MODEL_SPACE,pDb,AcDb::kForWrite);
	if (Acad::eOk != pBlkRcd.openStatus())
	{
		acutPrintf(_T("\n打开块表记录失败!,错误码: %s"),acadErrorStatusText(pBlkRcd.openStatus()));
		return;
	}
	es = pBlkRcd->appendAcDbEntity(pCircle);
	if (Acad::eOk == es)
	{
		acutPrintf(_T("\n添加实体成功!"));
	}
}

  我可以看到,以上代码没有使用close来关闭打开的对象.其原理就是用AcDbObjectPointer打开对象在释放这个变量的时候,利用析构函数来close或者delete处理,

简单看下这个类模板的析构函数.

选择AcDbObjectPointer 按F12转到定义,他的基类为AcDbObjectPointerBase,我们找这个类的析构函数

template<class T_OBJECT>
class AcDbObjectPointer : public AcDbObjectPointerBase<T_OBJECT>
{
public:
    AcDbObjectPointer();
    AcDbObjectPointer(AcDbObjectId   objId,
                      AcDb::OpenMode mode = AcDb::kForRead,
                      bool           openErased = false);

#if DBOBJPTR_EXPOSE_PTR_REF
    AcDbObjectPointer(T_OBJECT * pObject);
    void operator=(T_OBJECT *pObject);
#endif

    Acad::ErrorStatus open(AcDbObjectId objId,
                      AcDb::OpenMode    mode = AcDb::kForRead,
                      bool              openErased = false);

private:
    // Copy and assignment prohibited.
    AcDbObjectPointer(const AcDbObjectPointer &) = delete;
    AcDbObjectPointer& operator=(const AcDbObjectPointer &) = delete;
};

typedef AcDbObjectPointer<AcDbDictionary> AcDbDictionaryPointer;
typedef AcDbObjectPointer<AcDbEntity>     AcDbEntityPointer;

  析构函数.

template<class T_OBJECT> inline
AcDbObjectPointerBase<T_OBJECT>::~AcDbObjectPointerBase()
{
    if (m_ptr != NULL) {
        assert(m_status == Acad::eOk);
        Acad::ErrorStatus closeStatus = closeInternal();
        (void)closeStatus;
        assert(closeStatus == Acad::eOk);
    }
}

  关键的函数是closeInternal()

下面是源码

template<class T_OBJECT> inline Acad::ErrorStatus
AcDbObjectPointerBase<T_OBJECT>::closeInternal()
{
    if (m_ptr == NULL)
        return Acad::eOk;
    Acad::ErrorStatus es = Acad::eOk;
    if (m_ptr->objectId().isNull()) {
        delete m_ptr;
        es = Acad::eOk;
    } else {
        es = m_ptr->close();
    }
    m_ptr       = NULL;
    m_status    = Acad::eNullObjectPointer;
    return es;
}

  我们可以看到,如果没有加入到数据库,也就是对象Id为空,就直接delete释放对象.否则就执行close处理.

以上就是arx智能指针的浅析.

下面这几个智能指针的成员函数比较常用

    Acad::ErrorStatus openStatus() const;

    Acad::ErrorStatus open(AcDbObjectId   objId,
                           AcDb::OpenMode mode = AcDb::kForRead,
                           bool           openErased = false);

    Acad::ErrorStatus acquire(T_OBJECT *& pObjToAcquire);
    Acad::ErrorStatus release(T_OBJECT *& pReleasedObj);
    Acad::ErrorStatus close();

    Acad::ErrorStatus create();

  open()不需要多说.就是打开对象.

  openStatus()存放打开状态的记录值,

  acquire() 这个是可以把已经用其他方式打开的对象,比如用acdbOpenAcDbEntity打开的对象转换为智能指针对象,

      这样就可以不需要刻意处理close,再比如你clone克隆的实体,偏移的实体,打断的实体,也可以转换到智能指针方式.

  release()释放对象,和acquire应该是相反的操作,就是把对象转给普通指针处理,不再自动close处理.

  close()关闭对象,调用closeInternal();不是简单close,注意智能指针的pEnt.close()和pEnt->close();这不是同一个函数.

  create(),创建对象,就是new对象.

符号表,符号表记录均有类似的智能指针操作,大同小异.不再叙述.

原文地址:https://www.cnblogs.com/edata/p/12643930.html

时间: 2024-11-10 05:34:30

浅谈ObjectARX智能指针AcDbObjectPointer的用法的相关文章

浅谈RAII&智能指针

关于RAII,官方给出的解释是这样的"资源获取就是初始化".听起来貌似不是很懂的哈,其实说的通俗点的话就是它是一种管理资源,避免内存泄漏的一种方法.它可以保证在各种情况下,当你对对象进行使用时先通过构造函数来进行资源的分配和初始化,最后通过析构函数来进行清理,有效的保证了资源的正确分配和释放.(特别是在异常中,因为异常往往会改变代码正确的执行顺序,这就很容易引起资源管理的混乱和内存的泄漏) 其中智能指针就是RAII的一种实现模式,所谓的智能就是它可以自动化的来管理它所指向那份空间的资源

浅谈C++智能指针

操作内存 创建内存:new 过程:用new创建内存,如果成功的话那么直接分配,然后调用对象的构造函数,如果分配不够,那么先去调用用户自己写的set_new_handler函数,一般这个函数是用来释放些内存,然后使多点内存,然后再去申请,如果还是不行,再调用该函数,但是一般就是用个标记变量释放第一次,第二次直接退出,然后会返回一个bad_alloc错误 释放内存:delete 过程:调用析构函数,然后释放内存,如果释放一个数组,那么就是找到数组前几个字节,一般有个保存长度的东西 智能指针 原因:因

转 浅谈C++中指针和引用的区别

浅谈C++中指针和引用的区别 浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a

C++ 浅谈C++中指针和引用

浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单

浅谈为什么只有指针能够完成多态及动态转型的一个误区

c++多态由一个函数地址数组Vtable和一个指向Vtable的指针vptr实现. 具体来说,类拥有自己的vtable,类的vtable在编译时刻完成. 每个对象有自己的vptr指针,该指针初始化时指向对象所实现的类的vtable. 关于向上转型的误区: 通常对于向上转型的理解是这样的,当子类对象向上转型(允许隐式)成父类对象时,实际上只是将子类对象暂时看做父类对象,内部的数据并未改变. 对于没有虚函数的对象,这句话是正确的,但是,当引入虚函数后,这样的理解是有问题的,实际上,向上转型的过程中,

libsvm代码阅读(2):svm.cpp浅谈和函数指针(转)

svm.cpp浅谈 svm.cpp总共有3159行代码,实现了svm算法的核心功能,里面总共有Cache.Kernel.ONE_CLASS_Q.QMatrix.Solver.Solver_NU.SVC_Q.SVR_Q 8个类(如下图1所示),而它们之间的继承和组合关系如图2.图3所示.在这些类中Cache.Kernel.Solver是核心类,对整个算法起支撑作用.在以后的博文中我们将对这3个核心类做重点注解分析,另外还将对svm.cpp中的svm_train函数做一个注解分析. 图1 图2 图3

谈c++智能指针

在软件框架设计过程中,若引入智能指针来实现内存的自动管理,那意味着不得不放弃c++面向对象以虚函数为基础实现多态来提供统一接口的特性,从而采用模板来提供接口. 为什么c++不引入内存自动管理机制? c++这门程式设计语言的初衷就是不为程序员强加更多的枷锁,当然,这样会使该程式语言的易用性.可掌握性不如java, python(程序员不需再关注内存管理). 但java, python在某些应用场合却不得不让位于c++,例如实时控制系统.操作系统编程.

浅谈C++中指针和引用的区别

指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址. 而下面2句定义了一

浅谈数组与指针

对于一维数组与指针: 对于二维数组与指针: