Symbian 学习日志(三. cleanup)

本文介绍了CleanupStack类的使用方法,包括不同方式的清除操作、针对非CBase类的使用技巧,以及通过TCleanupItem实现自定义清理逻辑。还展示了如何通过模板函数简化常见资源释放操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

一、Cleanup 类的使用

 

//ClearnupStack 类定义

class CleanupStack

{

public:

      IMPORT_C static void PushL(TAny* aPtr);

      IMPORT_C static void PushL(CBase* aPtr);

      IMPORT_C static void PushL(TCleanupItem anItem);

      IMPORT_C static void Pop();

      IMPORT_C static void Pop(TInt aCount);

      IMPORT_C static void PopAndDestroy();

      IMPORT_C static void PopAndDestroy(TInt aCount);

      IMPORT_C static void Check(TAny* aExpectedItem);

      inline static void Pop(TAny* aExpectedItem);

      inline static void Pop(TInt aCount, TAny* aLastExpectedItem);

      inline static void PopAndDestroy(TAny* aExpectedItem);

      inline static void PopAndDestroy(TInt aCount,

           TAny* aLastExpectedItem);

};

 

建议使用PopAndDestroy(变量名的方式)

void ContrivedExampleL()

{// Note that each object is pushed onto the cleanup stack

      // immediately it is allocated, in case the succeeding allocation

      // leaves.

      CSiamese* sealPoint = NewL(ESeal);

      CleanupStack::PushL(sealPoint);

      CSiamese* chocolatePoint = NewL(EChocolate);

      CleanupStack::PushL(chocolatePoint);

      CSiamese* violetPoint = NewL(EViolet);

      CleanupStack::PushL(violetPoint);

      CSiamese* bluePoint = NewL(EBlue);

      CleanupStack::PushL(bluePoint);

 

      sealPoint->CatchMouseL();

      // Other leaving function calls, some of which use the cleanup stack

      // Various ways to remove the objects from the stack and delete them:

      // (1) All with one anonymous call - OK, but potentially risky

      // CleanupStack::PopAndDestroy(4);

      // (2) All, naming the last object - Better

      // CleanupStack::PopAndDestroy(4, sealPoint);

      // (3) Each object individually to verify the code logic

      // Note the reverse order of Pop() to PushL()

      // This is quite long-winded and probably unnecessary in this

 

      // example

      CleanupStack::PopAndDestroy(bluePoint);

      CleanupStack::PopAndDestroy(violetPoint);

      CleanupStack::PopAndDestroy(chocolatePoint);

      CleanupStack::PopAndDestroy(sealPoint);

}

 

二、带C结束的函数:

如果将一个新建类压到CleanupStack 中并且在退出函数前不清除它,就应该在函数名后面加C

 

CSiamese* CSiamese::NewLC(TPointColor aPointColour)

{

      CSiamese* me = new (ELeave) CSiamese(aPointColour);

      CleanupStack::PushL(me); // Make this leave-safe...

      me->ConstructL();

      return (me) // Leave "me" on the cleanup stack for caller to Pop()

}

 

 

三、Non-CBase Classes 如何使用 Cleanup

 

CleanUpStack 的使用上都是存的 TCleanupItem 这个类,不存是不是从CBase 派生而来

TCleanUpOperation 定义

// From e32base.h

typedef void (*TCleanupOperation)(TAny*);

//

class TCleanupItem

{

public:

      inline TCleanupItem(TCleanupOperation anOperation);

      inline TCleanupItem(TCleanupOperation anOperation, TAny* aPtr);

 

private:

      TCleanupOperation iOperation;

      TAny* iPtr;

      friend class TCleanupStackItem;

};

 

 

四、使用TCleanupItem的例子,直接使用P

 

class RSample

{

public:

      static void Cleanup(TAny *aPtr);

      void Release();

      ... // Other member functions omitted for clarity

};

// cleanup function

void RSample::Cleanup(TAny *aPtr)

{// Casts the parameter to RSample and calls Release() on it

      // (error-checking omitted)

      (static_cast<RSample*>(aPtr))->Release();

}

 

void LeavingFunctionL()

{

      RSample theExample;

      TCleanupItem safeExample(RSample::Cleanup, &theExample);

      CleanupStack::PushL(safeExample);

      // Some leaving operations called

      theExample.InitializeL(); // Allocates the resource

 

      // Remove from the cleanup stack and invoke RSample::Cleanup()

      CleanupStack::PopAndDestroy();

}

 

 

五、CleanupReleasePushL(T& aRef)

 

release函数调用的使用:

// Template class CleanupRelease

template <class T>

inline void CleanupRelease<T>::PushL(T& aRef)

{CleanupStack::PushL(TCleanupItem(&Release,&aRef));}

template <class T>

void CleanupRelease<T>::Release(TAny *aPtr)

{(STATIC_CAST(T*,aPtr))->Release();}

template <class T>

inline void CleanupReleasePushL(T& aRef)

{CleanupRelease<T>::PushL(aRef);}

 

class CClanger : public CBase, MExtraTerrestrial

{

public:

      static MExtraTerrestrial* NewL();

      virtual void CommunicateL(); // From MExtraTerrestrial

      virtual void Release();

private:

      CClanger();

      ();

private:

      ...

};

void TestMixinL()

{

      MExtraTerrestrial* clanger = CClanger::NewL();

      CleanupReleasePushL(*clanger); // The pointer is deferenced here

      ... // Perform actions which may leave

      CleanupStack::PopAndDestroy(clanger); // Note pointer to the object

}

 

六.CleanupDeletePushL(T& aRef)

 

// Template class CleanupDelete

template <class T>

inline void CleanupDelete<T>::PushL(T* aPtr)

{CleanupStack::PushL(TCleanupItem(&Delete,aPtr));}

template <class T>

void CleanupDelete<T>::Delete(TAny *aPtr)

{delete STATIC_CAST(T*,aPtr);}

template <class T>

inline void CleanupDeletePushL(T* aPtr)

{CleanupDelete<T>::PushL(aPtr);}

 

七、CleanupClosePushL(T& aRef)

 

void UseFilesystemL()

{

      RFs theFs;

      User::LeaveIfError(theFs.Connect());

      CleanupClosePushL(theFs);

      ... // Call functions which may leave

           CleanupStack::PopAndDestroy(&theFs);

}

 

八、使用TCleanupItem 自定义删除

 

传统的不使用自定义删除的方法:

class CSpreadSheet : public CBase

{

public:

      // Guarantees an atomic update

      void UpdateSpreadSheetL(const CUpdate& aUpdate);

      ... // Other methods omitted

private:

      // Recalculates the contents of iSpreadSheet

      void RecalculateL(const CData& aData);

      void UpdateL(); // Updates iSpreadSheetView

      void RollBack(); // Reverts to the previous state

private:

      CExampleSpreadSheet* iSpreadSheet; // Defined elsewhere

      CExampleSpreadSheetView* iSpreadSheetView; // Defined elsewhere

      ...

};

 

void CSpreadSheet::UpdateSpreadSheetL(const CUpdate& aUpdate)

{

      TRAPD(result, RecalculateL(aData)); // Performs the recalculation

      if (KErrNone==result) // if no error, update the view

      {

           TRAP(result, UpdateL());

      }

      if (KErrNone!=result) // RecalculateL() or UpdateL() failed

      {

// Undo the changes

           RollBack();

           User::Leave(result);

      }

}

 

使用自定义删除的方法:

class CSpreadSheet : public CBase

{

public:

      // Guarantees an atomic update

      void UpdateSpreadSheetL(const CUpdate& aUpdate);

      ... // Other methods omitted

private:

      // Recalculates the contents of iSpreadSheet

      void RecalculateL(const CData& aData);

      void UpdateL(); // Updates iSpreadSheetView

      // Reverts to the previous state

      static void RollBack(TAny* aSpreadSheet);

      void DoRollBack();

private:

      CExampleSpreadSheet* iSpreadSheet;

      CExampleSpreadSheetView* iSpreadSheetView;

      ...

};

void CSpreadSheet::UpdateSpreadSheetL(const CUpdate& aUpdate)

{

      // Initialize the TCleanupItem

      TCleanupItem cleanup(CSpreadSheet::RollBack, this);

      CleanupStack::PushL(cleanup); // Put it on the cleanup stack

      RecalculateL(aData);

      UpdateL();

      CleanupStack::Pop(&cleanup); // TCleanupItem is no longer required

}

 

void CSpreadSheet::Rollback(TAny* aSpreadSheet)

{

      ASSERT(aSpreadSheet);

      CSpreadSheet* spreadsheet = static_cast<CSpreadSheet*>(aSpreadSheet);

      spreadsheet->DoRollBack();

}

 

九、类型转换宏定义

#define CONST_CAST(type,exp) (const_cast<type>(exp))

#define STATIC_CAST(type,exp) (static_cast<type>(exp))

#define REINTERPRET_CAST(type,exp) (reinterpret_cast<type>(exp))

#if defined(__NO_MUTABLE_KEYWORD)

#define MUTABLE_CAST(type,exp) (const_cast<type>(exp))

#else

#define MUTABLE_CAST(type,exp) (exp)

#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值