如何定义一个只能在堆上生成对象的类

来源:互联网 发布:加工中心钻孔6等份编程 编辑:程序博客网 时间:2024/05/22 03:18

这道题主要考察我们对于C++的语法的理解和运用的程度。

在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。

  • 静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。

  • 动态建立类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步,

    1. 第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配;

    2. 第二步是调用构造函数构造对象,初始化这片内存空间。这种方法,间接调用类的构造函数。

那么如何限制类对象只能在堆上生成呢?

本文主要给出以下两个方法

方法一:设置构造函数为私有。使用静态函数来new

类的对象只能创建在堆上,意味着不能静态建立类对象,即不能直接调用类的构造函数。

那我们把类的构造函数变成私有的,此时我们无法在类的外部调用构造函数来构造类的对象,只能使用new来建立对象。

因此我们可以在内部new上一个对象,并且提供一个公共接口来返回这个对象即可,所以我们把这个公共接口给成静态,防止外部无法通过类对象来调用类成员函数。

代码实现如下:

class  A  {  protected :      A(){}      ~A(){}  public :      static  A* create()      {          return   new  A();      }      void  destory()      {          delete   this ;      }  };  

方法二:析构函数给成私有

析构函数给成私有的,编译器无法调用类的析构函数来释放内存,所以编译器会首先检查类的析构函数的访问性,如果发现类的析构函数是私有的,编译器就不会再栈上为类对象分配内存,此时类对象就无法在栈上生成对象了。

class AA  {  public:         void destory()         {                delete this;         }  private:         ~AA()         {         }  };  void test2()  {         AA *a=new AA;              //可以         a->destory();  } 

但这样做有这样的缺点:

  • 无法解决继承问题。如果我们写的类作为其它类的基类,则析构函数通常要设为virtual,然后在子类重写,以实现多态。因此析构函数不能设为private。还好C++提供了第三种访问控制,protected。将析构函数设为protected可以有效解决这个问题,类外无法访问protected成员,子类则可以访问。

  • 另一个问题是,类的使用很不方便,使用new建立对象,却使用destory函数释放对象,而不是使用delete。(使用delete会报错,因为delete对象的指针,会调用对象的析构函数,而析构函数类外不可访问)这种使用方式比较怪异。为了统一,可以将构造函数设为protected,然后提供一个public的static函数来完成构造,这样不使用new,而是使用一个函数来构造,使用一个函数来析构。代码如下,类似于单例模式:

class  A  {  protected :      A(){}      ~A(){}  public :      static  A* create()      {          return   new  A();      }      void  destory()      {          delete   this ;      }  };  
阅读全文
0 0
原创粉丝点击