这道题主要考察我们对于C++的语法的理解和运用的程度。
在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。
静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。
动态建立类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步,
第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配;
第二步是调用构造函数构造对象,初始化这片内存空间。这种方法,间接调用类的构造函数。
那么如何限制类对象只能在堆上生成呢?
本文主要给出以下两个方法
方法一:设置构造函数为私有。使用静态函数来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 ;
}
};