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

来源:互联网 发布:中国国玺云计算 编辑:程序博客网 时间:2024/05/21 21:34

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

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

动态建立一个类对象,是使用new运算符将对象建立在堆空间上的,这个过程分为两步,第一步是
调用operator new()函数,在堆空间中搜索合适的内存并进行分配,第二步是调用类的构造函数构造
对象,初始化这片空间,这种方法间接调用类的构造函数;

1.只能在堆上建立对象:
对象只能建立在堆上,那么就说明不能直接调用构造函数,所以我们可以想到将构造函数私有化,
但是这样也不行因为任意一种方法,都会调用类的构造函数;当对象建立在栈上,是由编译器为它
分配空间,当对象使用结束后,编译器会对它进行回收,由此可知编译器管理了它的整个生命周期;
如果我们私有化了析构函数,使编译器无法回收这块空间,那么编译器就不会在栈空间上开辟空间了;

class A{public:    A()    {}    void Destory()    {        delete this;    }private:    ~A()    {}private:    int _a;};void TestA(){    A* a = new A;    a->Destory();}

这样就只能使用new操作符来建立对象,构造函数是公有的,可以直接调用,但是必须提供一个Destory
来进行内存空间的释放;类对象使用完成后必须使用Destory函数;

上述方法存在一个缺点:无法解决继承问题,如果A类作为其它类的基类,则析构函数通常设为virtual,
然后在子类中进行重写,以实现多态;因此析构函数不能设为private,可以将其设为protected:子类可以
访问,外部类不能访问;

另一个问题是,类的使用并不方便,使用new建立对象,却使用Destory函数释放对象,而不能使用
delete,(因为使用delete,delete对象的指针会调用析构函数,而析构函数类外不能访问);

因此,我们可以将构造函数设为protected:然后提供一个public的static函数完成构造,这样不使用new,
而是使用一个函数来构造,使用一个函数来析构;

class A{public:    static A* Create()    {        return new A;    }    void Destory()    {        delete this;    }private:    A()    {}    ~A()    {}private:    int _a;};void TestA(){    A* a = A::CreateObj();    a->Destory();}

这样调用Create函数在堆上创建A对象,调用Destory函数释放内存;

2.只能建立在栈上:
只有使用new操作符,对象才会建立在堆上,因此只要禁用new操作符,就可以实现类对象只能建立在
栈上。将operator new设为私有即可。

class A{public:    A()    {}    ~A()    {}private:    void* operator new(size_t t)    {}    void operator delete(void* ptr)    {}private:    int _a;};void TestA(){    A a;}
阅读全文
0 0
原创粉丝点击