有时候你会想要做这样的安排:让某种类型的对象有“自杀”能力,也就是说能够"delete this"。如此安排很明显要求该类型对象被分配于heap内。另外一些时候你可能想要拥有某种确定性,保证某一类型绝不会发生内存泄露(memory leak),原因是没有任何一个该类型的对象从heap中分配出来。假设你从事嵌入式系统工作,这类系统如果发生内存泄露,是非常麻烦的事情,因为heap空间极其宝贵。我们有没有一些可能完成一些代码,要求或禁止对象产生于heap之中呢?通常可以,但结果证明,所谓的“在heap中”可能比你想象的更含糊。
要求对象产生于heap之中(所谓Heap-Based Objects)
让我们从“限制对象必须诞生于heap”开始。为了严厉执行此等限制,你必须找出一个方法,组织clients不得使用new以为的方法产生对象。这很容易做到。是的,non-heap objects会在其定义时自动构造,并在其寿命结束时自动析构,所以只要让那些被隐式调用的构造动作和析构动作不合法,就可以了。
欲令这些动作不合法,最直截了当的方式就是讲constructors和destructor声明为private。但这实在太过了,没有理由让它们都成为private。比较好的办法是让destructor成为private,而constructors仍为public。如此一来,利用条款26所介绍的程序,你可以导入一个pseudo(伪的)destructor函数,用来调用真正的destructor。clients则调用这个pseudo-destructor以销毁它们所产生的对象。
假如,我们希望确保“表现无限精度”的数值对象只能诞生于heap之中,可以这么做:
-
class UPNumber
-
{
-
public:
-
UPNumber();
-
UPNumber(int initvalue);
-
UPNumber(double initvalue);
-
UPNumber(const UPNumber &rhs);
-
-
//pseudo(伪的)destructor。这是一个const member function
-
//因为const也可能需要被销毁
-
void destroy() const
-
{
-
delete this;
-
}
-
private:
-
~UPNumber(); //注意:析构函数位于private之内
- };
-
UPNumber n; //错误:虽然合法,但当n的析构函数
-
//稍后被隐式调用,就不合法了。
-
UPNumber *p = new UPNumer; //良好
-
...
-
delete p; //错误!企图调用private destructor
- p->destroy(); //良好
所以比较容易的办法还是只声明destructor为private,因为一个class只能有一个析构函数。
只要限制了destructor或constructors的运用,便可阻止non-heap objects的诞生。但是,就如条款26所说,它也妨碍了继承和内含:
-
class UPNumber
-
{
-
//将constructors或destructor声明为private
-
};
-
-
class NoNegativeUPNumber: //这是继承
-
public UPNumber //错误!constructors或destructor无法通过编译
-
{
-
......
-
};
-
-
class Asset //这是内含
-
{
-
private:
-
UPNumber value; //错误:constructors或destructor无法通过编译
- };
至于“必须内含UPNumber对象”之classes,可以改为“内含一个指针,指向UPNumber对象”。
-
class UPNumber
-
{
-
//注意:将destructor声明为protected
-
};
-
-
class NoNegativeUPNumber: //这是继承
-
public UPNumber //现在没有问题了:derived class
-
//可以取用protected members
-
{
-
......
-
};
-
-
class Asset
-
{
-
public:
-
Asset(int initvalue);
-
~Asset();
-
.....
-
private:
-
UPNumber *value; //..............
-
};
-
-
Asset::Asset(int initvalue):value(new UPNumber(initvalue)) //ok
-
{
-
//......
-
}
-
Asset::~Asset()
-
{
-
value->destroy(); //ok
- }
引自:《More effective C++中文版》