在C++中,类的对象的建立分为两种,一种是静态建立,比如A a;一种是动态建立,比如A * a=new A();
对于静态建立而言,编译器将栈顶指针的位置分配给a,并且直接调用a的构造函数,将栈顶指针后移,而对于动态建立而言,编译器搜索堆中可用的空间,将它分配给a,然后间接调用a的构造函数来构造a
1.如何将类只能初始化在堆上
容易想到将构造函数设为私有。在构造函数私有之后,无法在类外部调用构造函数来构造类对象,只能使用new运算符来建立对象。然而,前面已经说过,new运算符的执行过程分为两步,C++提供new运算符的重载,其实是只允许重载operator new()函数,而operator()函数用于分配内存,无法提供构造功能。因此,这种方法不可以。
所以,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性,其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。
因此,将析构函数设为私有,类对象就无法建立在栈上了。代码如下
所以,代码如下:
Class A
{
Public:
A(){};
Voiddestroy() {delete this;}
Private:
~A(){};
}
构造函数可以直接调用。类中必须提供一个destory函数,来进行内存空间的释放。类对象使用完成后,必须调用destory函数,因为析构函数是私有的,不能通过delete来释放对象,系统也无法自动释放对象。
上述方法的一个缺点就是,无法解决继承问题。如果A作为其它类的基类,则析构函数通常要设为virtual,然后在子类重写,以实现多态
因此可以将析构函数设置为protected类型以实现需要的功能
但是使用New声明使用destroy释放有点奇怪,因此使用creat函数声明
Class A
{
Public:
StaticA* creat()
{
Return new A();
}
Voiddestroy() {delete this;}
protected:
~A(){};
A(){};
}
这样就实现了类只能在堆中初始化而不能在栈中初始化
2.如何将类只能初始化在栈上
首先类假如需要初始化在堆上,其需要new运算符,我们可以重载new运算符,将其设为私有或者是保护类型,来使得类只能初始化在栈上,
这里需要说一下C++的new运算符,C++的new运算符有三种,1一种是我们平时常用的那一种,new operator,它的功能是调用后两种new来进行类的初始化,2第二种是operator new,只有这一种可以重载重载它的时候参数为size_t 3第三种为placement new,这一种用来初始化对象,用来调用构造函数
Class A
{
private:
void* operator(size_t t)
{}
Void operator delete (void * ptr)
{}
Public:
~A(){};
A(){};
}
这里面的delete的重载可以加上去,也可以不加上去