zoukankan      html  css  js  c++  java
  • 【M26】限制某个class所能产生的对象数量

    1、每当产生一个对象,必定调用构造方法。因此,禁止产生对象的做法就是,将所有的构造方法声明为private。

    2、只有在类的内部才可以访问private成员,有两层含义:在类的内部可以访问this的private成员,同时可以访问同类对象的private成员。

    3、将构造方法声明为private,只是限制了在外部调用构造方法产生对象,还是有办法可以产生对象。办法有:

      a、类暴露一个static方法,在static方法内部调用private构造方法,产生对象返回。

      b、在类中声明友元方法,或者友元类,这样的话,就可以访问该类的private构造方法。

    4、考虑,只产生一个对象。该怎么办?使用友元方法,内部有static对象,返回static对象的引用。比如:只产生一个打印机。

      在类中声明:friend Printer& thePrinter();

      实现为:

      printer& thePrinter()

      {

        static Printer p;

        return p;

      }

    5、上面的方式有个问题,友元方法是个全局方法,意味着放大了作用域。有没有更好的办法呢?

      a、第一个办法是,使用命名空间,将与Printer有关的内容放在这个命名空间内,这样就缩小了作用域。

      b、第二个方法是,让类暴露一个static方法。如下:

      在类中声明:static Printer& thePrinter();

      实现为:

      Printer& Printer::thePrinter()

      {

        static Printer p;

        return p;

      }

      从封装的角度看,类本身表示一个范围,可以认为命名空间的意思。只不过,命名空间内的东西都是public,而类中可以细化为public,protected,private。

    6、现在考虑,方法中的static对象。

      a、首先一点,对于方法中的static对象,也就是local static对象,方法不被调用,static对象就绝不会产生。而对于non-local static对象(包括全局对象,命名空间内的对象,file作用域,class中的static对象),即使从未被调用,也要构造析构对象。从c++的角度看,不要为不使用的东西产生代价。因此,使用local static对象更好。

      b、还有第二点,在一个编译单元内的static对象,C++保证按声明的顺序初始化,而对于不同编译单元内的static对象,顺序是不确定的,因此,程序员不能依赖某种初始化顺序。而对于,方法中的static对象,确定是第一次调用方法的时候,初始化static对象。

      c、还有一点,这个方法不能声明为inline,思考为什么?这个方法中,使用static,目的就是,返回的引用都是这个static对象。假如使用inline,可认为编译器在每个调用的地方进行文本替换,这样的话,就会产生多个static对象,这明显不是我们所期望的。

    7、现在考虑,更一般化的问题。比如,我们有5个打印机,如何限制产生的对象个数不能大于5?

      在类中维护两个字段:已经产生的对象个数NumObjects和允许最多的对象个数MaxObjects,这两个字段对类和所有对象有意义,因此是static。每次构造对象的时候,检查NumObjects<MaxObjects,条件满足,++NumObjects,构造一个新对象返回。条件不满足,抛出一个异常。每次析构对象的时候,--NumObjects。

    8、上面的方式,在调用构造方法的时候,对NumObjects累加。这将导致下面的两个问题:

      a、考虑,ColorPrinter继承Printer,实例化ColorPrinter对象的时候,会调用Printer 的构造方法,对NumObjects累加,这不是我们所期望的。

      b、考虑类A中内含Printer对象,A a1,a2; 导致调用Printer构造方法两次,这也不是我们所期望的。

    9、怎么解决上面的问题? 问题的关键是Printer对象在3种状态下生存:a、它自己;b、子类的父类成分中;c、内嵌于其它对象中。因此,解决的办法是,禁止后面的两种状态。也就是将构造方法声明为private。 构造方法声明为private,不能被继承,同时不能在外部调用构造方法构造对象。但同时,又必须产生对象给外部用,也就是上面的方法:类暴露static方法,或者类中声明友元方法或者友元类。

    10、考虑下面的问题,如果有很多类似Printer的类,该怎么办呢?

      把共用的代码放到父类中,父类负责管理对象的个数,因为可以对不同的类封装,因此父类是模板类。如下:

      class Printer: private Counted<Printer>

  • 相关阅读:
    [网鼎杯 2018]Comment-Git泄露部分
    Google Hacking 详解
    macOS修改Docker容器的端口映射配置
    CentOS6 7 8更换阿里yum源
    XSS代码合集(含测试效果详细版)-HTML4与更早版本的向量2
    VMware 启动Ubuntu时黑屏
    XSS代码合集(含测试效果详细版)-HTML4与更早版本的向量1
    APP安全在线检测网站
    Juice-Shop 二星题
    慕课网-安卓工程师初养成-4-5 练习题
  • 原文地址:https://www.cnblogs.com/nzbbody/p/3576440.html
Copyright © 2011-2022 走看看