摘抄自
http://www.newlc.com/inside-cbase-class-six-essential-questions
如果你可以回答下面的6个问题,那么你可以不用看这篇文章了
- 为什么Cleanup Stack有3个不同的PushL函数?
- 为什么CBase有public的析构函数
- CBase是怎么让它的子类初始化为0的
- 为什么要初始化为0
- 为什么不建议用new[]初始化CBase的继承类
- 为什么CBase有private 的拷贝构造函数和private的"="重载
下面是这6个问题的答案:
- Cleanup Stack可以保证出现异常时被压栈的对象成功释放内存。释放内存的方法有2种,调用delete(将调用析构函数)或者调用User::Free()。对于TAny指针指向的内容,Cleanup Stack在退出时候将仅调用User::Free(),这个时候需要用PushL(TAny*)。通常的CBase对象,则调用delete,这个时候用PushL(CBase*)。如果需要压入Cleanup Stack,又不想用CBase,则使用PushL(TCleanupItem)。
- 因为需要被Cleanup Stack调用,所以应该是public,因为多态的需要,应该是virtual。
- CBase重载了new函数,调用AllocZL分配内存,自然会初始化为0
- 继承自CBase的类被压栈后即使出现异常也能保证析构函数被调用。那么,如果它有一个成员变量是一个指针,在析构时需要根据这个指针是否NULL判断是否需要回收这个指针指向的内存,如果这个指针没有被初始化,在运行过程中发生异常,那么析构的时候这个指针就是野指针,删除它会让程序崩溃的。看一段代码就明白了。
CTest* CTest::NewLC()
{
CTest* self = new ( ELeave ) CTest;
CleanupStack::PushL( self );
self->ConstructL()
return self;
}
void CTest::ConstructL()
{
iPointer = CMustLeave::NewL(); // assume this leaves
}
CTest::~CTest()
{
if( iPointer )
{
delete iPointer;
iPointer = NULL;
}
}如果iPointer没有初始化为NULL,则通过Cleanup Stack析构时可能导致程序崩溃。
- CBase并没有重装new[],如果使用new[]创建CBase的继承类对象,CBase的new重载函数则没有被调用,自然不会初始化CBase对象为0。如果需要创建对象的数组,可以用RPointerArray。
- 保证不被隐式的拷贝,你不能写诸如下面的代码
CBase* pointer = new ( ELeave ) CBase;
CBase base = *pointer; // call copy constructor编译器会报错
CBase* pointer = new ( ELeave ) CBase;
CBase base;
base = *pointer; // call operator =这样防止的不被注意的浅拷贝问题,如果需要一个深拷贝函数,可以实现一个自己的public克隆函数例如CloneL()
No comments:
Post a Comment