目录
前言
- 为了限制对象只能在 堆上 分配,需要将构造函数私有化并提供一个静态工厂函数,同时限制析构函数的访问权限。
- 为了限制对象只能在 栈上 分配,可以通过删除
new
操作符的重载来阻止堆分配。
1. 只允许在堆上分配对象
为了保证对象只能在堆上分配,可以使用以下方式:
- 将构造函数设为私有(private): 这样做可以防止外部直接在栈上创建对象(即不能使用
ClassName obj;
),但这也意味着外部无法直接通过new
来创建对象。 - 提供一个静态成员函数来创建对象: 我们可以提供一个
public
的静态函数,通过new
来创建对象,并返回指向该对象的指针。 - 将析构函数设为受保护的(protected): 这可以防止外部直接调用析构函数来删除对象,因为只允许通过特定的途径(比如
delete
)来销毁对象。
示例代码:
class MyClass {
private:
MyClass() {} // 私有构造函数
protected:
~MyClass() {} // 受保护的析构函数
public:
static MyClass* create() {
return new MyClass(); // 只能通过 new 创建对象
}
void destroy() {
delete this; // 提供一个成员函数来释放内存
}
};
解释: 构造函数是私有的,因此无法直接在栈上创建对象。只能通过 create()
静态函数来在堆上分配对象。destroy()
成员函数用于安全地删除对象,因为析构函数是受保护的,外部无法直接调用 delete
。
2. 只允许在栈上分配对象
如果要保证对象只能在栈上分配,则需要禁止使用 new
在堆上分配对象,可以通过重载 new
操作符来实现:
- 重载
new
操作符使其功能为空: 通过让new
操作符不可用,可以阻止对象在堆上创建。
示例代码:
class MyClass {
public:
void* operator new(size_t) = delete; // 禁止使用 new 操作符
void* operator new[](size_t) = delete; // 禁止使用 new[] 操作符
MyClass() {} // 普通构造函数
~MyClass() {} // 普通析构函数
};
解释: 重载 new
操作符并将其删除(= delete
),这意味着外部无法使用 new MyClass()
或 new MyClass[]
来在堆上创建对象。这样,只能在栈上分配对象(MyClass obj;
)。