一、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