我的C++实践(14):限制类对象的个数

    1、允许一个或零个对象: 把所有的构造函数声明为私有,则不能创建任何对象。如果允许只创建一个对象,可用一个全局函数(或静态成员函数)来创建唯一的一个静态对象,并返回其引用,为提高效率,可把全局函数声明为inline。注意这个全局函数要声明为类的友元函数,因为要使用私有的构造函数。
    例如我们想创建一个打印机对象,但希望实际上只有一个打印机,可以这样写:

 

    这里我们把thePrinter()实现为一个全局函数,里面只创建一个静态对象,返回其引用,这样客户端代码中的所有thePrinter()调用都只使用这个唯一的静态对象。注意,对构造函数,可以只声明为私有,如果不使用它,则可以不提供定义,但对需要被使用的构造函数(因为是私有,只能在类的成员函数或友元函数中使用)则必须提供定义。当然,我们也可以把thePrinter()实现为Printer类的静态成员函数,这样就不需要友元声明了。但使用全局函数也有优势,因为在某些类中声明的静态对象即使没用到也会被构造(以及析构)出来,而全局函数里的静态对象只有执行函数时才被创建。
    另一方面,我们有时候会把那个唯一的p对象声明为全局的静态对象或Printer类的静态成员,然后在thePrinter()或Printer::thePrinter()中直接返回它,这不是一种好的实现方案。我们称函数内的static对象称为local static对象,其他的static对象(class作用域、namespace作用域、global作用域、file作用域)称为non-local static对象。C++只保证在一个特定编译单元内的静态对象的初始化顺序,对不同编译单元内的non-local static对象的初始化次序没有明确定义。可见这样的实现方案会使得p对象的初始顺序不明确。
    当我们需要用到non-local static对象,又要保证正确的初始化顺序时,解决方法恰恰就是将non-local static对象放在一个inline包装函数中,函数返回一个引用指向此对象(变成local static对象)。用函数调用来替换直接访问non-local static对象,这时函数内的局部静态对象就会有确定的初始化顺序(在第一次执行函数时初始化)。注意,我们通常在设计时并不建议返回指向函数内局部对象的reference,但这里的包装函数行为单纯,只是包装一个static对象并返回其reference,并不做其他工作。当多次调用包装函数时,reference指向同一个static对象,并且值均相同(包装函数内并没有改变对象的成员值),因此这样实现没有副作用。
    注意,构造函数声明为私有的类不能作为基类使用,也不能组合到其他类中来使用。我们可以放宽一点,把构造函数声明为protected的,这样类同样不可以创建对象,但可以被继承。
    2、允许创建任意数量的对象,但不允许作为基类: 把构造函数声明为私有,这样就不允许作为基类了。同时我们提供相应的伪构造函数,用它来创建对象并返回。例如对有限状态机类,如下:

    客户端使用这个类时,就必须调用伪构造函数来创建对象。当然,由于对象是动态分配的,这时客户必须自己调用delete来删除对象。
    3、允许对象个数限制在某个给定的值: 使用前面在“模板与继承相结合的威力”中介绍的奇异递归模板模式技术,编写一个具有实例计数功能的基类即可,让需要计数的类继承这个类。因为类要实现计数功能,是一种“实现”的关系,故最好用私有继承,表示用这个基类来实现需要的功能。这里我们做一下修改,当需要计数的类对象个数超过上限时就抛出异常。注意不同的类可以通过特化这个基类的表示上限值的成员,以满足不同类对象个数的要求。

 

    这里ObjectCounter<T>模板用于计数,它需要作为基类,成员名的前面最好加类作用域符(也可用this->),使它变成依赖型名称。表示对象个数上限值的maxObjects成员是一个静态常量,它并没有初始化。我们必须在需要计数的类MyString、Printer中指定它的值。不同类的对象个数上限可能不同,因此我们只要特化maxObjects这个成员并指定需要的值即可(类模板可以只特化某个成员)。在MyString、Printer这些类中,由于是私有继承,因此要用using声明把objectCount函数变成公有,这样就可以用它来获取当前对象的个数。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值