您的位置:首页 > 编程语言 > C语言/C++

C++对象数量跟踪限制

2009-04-26 15:02 246 查看
在实际的编程中,有很多时候需要限制对象的数量,比如代表设备资源的对象,代表上线客户的对象等等。那么我们就需要对这些类型的对象进行数量跟踪限制,这样我们就必须在类定义中加入一些额外的信息。

实践中不难发现,需要这让功能的类加入的额外信息似乎大同小异,按照避免重复编码的原则,我们应该寻找另外一种解决方案使得不用或者少做这样的重复工作。

很显然,我们需要一个这样的类,它完成对象数量跟踪和限制的功能,并且能够很方便的被各种需要此功能类型所使用。它还必须具有隐藏性,因为实际的客户代码是不需要知道其信息的,这个类只能算个辅助类。那么它就不应该具有public访问权限的构造函数。

实现跟踪一类对象的数量并且进行限制,最简单的办法就是在这个类中定义两个静态成员:1、当前对象数量;2、最大对象数量。既然我们已经打算将这些信息封装到一个辅助类中,那自然这两个静态成员也应该成为辅助类的静态成员。不同的类去使用它的时候,其静态成员应该完全没有任何联系,那么就要想办法为每个使用它的类生成一份专有的类,能够完成这样功能的方法自然就是——模板。

需要对象数量跟踪限制功能的类怎么样来使用这个辅助模板类呢?使用包含的话?那么每个使用它的类都必须成为其友元,因为这个辅助模板类的构造函数不具有public访问权限,这很显然是不可能的。有一种方法可以访问一个类的非public成员——继承。派生类可以访问基类的protected成员,我们将辅助模板类的构造函数声明为protected访问权限,并让使用它的类继承于它,那么这个辅助类就可以发挥其功效了。

这里有个值得注意的问题:vtbl。一个继承关系上出现一个virtual关键字,那么肯定会影响到对象的大小和布局。然而从我们要完成的这个功能上看,虽然具有继承关系,但是根本没有必要使用到virtual。但是客户如何使用我们的类我们是无法猜测的,如果有个好奇的客户使用基类指针去删除一个派生类对象,而基类析构函数不带virtual关键字的话,那么带来的风险可能谁都不愿意承担。既然我们已经确定了不需要virtual,那么我们就要坚持,不要因为客户的这种操作来改变我们的行为。这种操作是我们不想看到的,那我们就去限制它!我们把删除基类的权限限制到派生类中,即基类析构函数声明为protected,那么客户就没有办法delete一个基类指针了,自然就不存在那种我们不想给予客户的操作了。

使用这个辅助的模板类来跟踪对象数量以及限制对象数量,除了我们编写派生类的人来说,其他人根本就不需要知道,那么它的实现细节最好应该是private的。private继承就能帮到你。

当对象的数量超过了最大值时,如何传递这个消息给客户呢,然而构造函数又没有返回值,这时C++异常机制可以帮助我们。辅助模板类应该在跟踪到对象数量达到上限时,客户再请求就传递一个通知给客户——即抛出一种TooManyObjects的异常。有时,已经存在的对象数量也可能成为客户所想了解的信息,那么辅助模板类还必须有一种能够让客户得到对象数量的方法,定义一个静态函数应该是最容易的方法。

这时我们应该回过头来看了,我们上面说到我们采用的是private继承,那么这个辅助模板基类的所有信息都成为了private,我们必须要将其public的成员恢复其访问权限。还好C++提供了using来让我们有机会恢复访问权限。在派生类的public中使用using来让基类public成员可见,这成员包括需要传递给客户的异常类和获取对象数量的静态函数。

到此为止,我们已经可以实现这样的一个辅助模板基类了。其使用的规则我们可以很容易编写一个文档来告诉给需要派生自它的客户了。

示例代码:

TakeCount.h文件

#ifndef TAKE_COUNT_H
#define TAKE_COUNT_H

/*---------------------------------------------------------------------------------------->
* 对象数量跟踪限制的模板基类TakeCount。 作者:Evil.Ghost *
* 需要跟踪限制对象数量的类private继承于它,并负责初始化其静态const成员maxObjects。 *
* 如果对象超出上限,那么在构造函数中将抛出TooManyObjects异常。 *
* 可以通过ObjectCount函数获取当前对象数量。 *
<----------------------------------------------------------------------------------------*/

// 模板的类型参数应传递派生类
template<class NeedTakeCount>
class TakeCount{
static int numObjects;
static const size_t maxObjects;

public:
class TooManyObjects{};
static int ObjectCount()
{
return numObjects;
}

protected:
TakeCount();
TakeCount(const TakeCount& rhs);
~TakeCount()
{
--numObjects;
}

private:
// 避免重复写构造代码的帮助函数
void Init();
};

/*------------------实现代码----------------------*/

template<class NeedTakeCount>
TakeCount<NeedTakeCount>::TakeCount()
{
Init();
}

template<class NeedTakeCount>
TakeCount<NeedTakeCount>::TakeCount(const TakeCount<NeedTakeCount>&)
{
Init();
}

template<class NeedTakeCount>
void TakeCount<NeedTakeCount>::Init()
{
if (numObjects >= maxObjects)
{
throw TooManyObjects();
}
++numObjects;
}

#endif // TAKE_COUNT_H

TakeCount.cpp文件

#include "TakeCount.h"

template<class NeedTakeCount>
int TakeCount<NeedTakeCount>::numObjects;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: