您的位置:首页 > 其它

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

2017-07-08 11:34 176 查看
在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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  对象