冷面面筋:如何将对象创建限制在堆或栈?
解决方法 1:
将析构函数设置为私有。原因:静态对象建立在栈上,是由编译器分配和释放内存空间,编译器为对象分配内存空间时,会对类的非静态函数进行检查,即==编译器会检查析构函数的访问性==。当析构函数设为私有时,编译器创建的对象就无法通过访问析构函数来释放对象的内存空间,因此,编译器不会在栈上为对象分配内存。
class A
{
public:
A() {}
void destroy()
{
delete this;
}
private:
~A()
{
}
};
该方法存在的问题:多态无法实现
用 new 创建的对象,通常会使用 delete 释放该对象的内存空间,但此时类的外部无法调用析构函数,因此类内必须定义一个 destroy() 函数,用来释放 new 创建的对象。无法解决继承问题,因为如果这个类作为基类,析构函数要设置成 virtual,然后在派生类中重写该函数,来实现多态。但此时,析构函数是私有的,派生类中无法访问。
解决方法 2:
构造函数设置为 protected,并提供一个 public 的静态函数来完成构造,而不是在类的外部使用 new 构造;将析构函数设置为 protected。原因:类似单例模式,也保证了在派生类中能够访问析构函数。通过调用 create() 函数在堆上创建对象。
class A
{
protected:
A() {}
~A() {}
public:
static A *create()
{
return new A();
}
void destroy()
{
delete this;
}
};
=================================
限制对象只能建立在栈上:
解决方法:将 operator new() 设置为私有。原因:当对象建立在堆上时,是采用 new 的方式进行建立,其底层会调用 operator new() 函数,因此只要对该函数加以限制,就能够防止对象建立在堆上。
class A
{
private:
// 注意函数的第一个参数和返回值都是固定的
void *operator new(size_t t) {
return nullptr;
}
void operator delete(void *ptr) {} // 重载了 new 就需要重载 delete
public:
A() {}
~A() {}
};