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

这道题主要考察我们对于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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值