C++类如何实现只能静态分配和只能动态分配
只能动态分配(只能通过 new创建在堆上)
核心思想:将析构函数设为 protected或 private。
为什么?
栈对象(静态分配)在离开作用域时,编译器会自动调用析构函数。如果析构函数不可访问,编译器会报错,从而阻止其在栈上创建。
new操作符分为两步:1. 分配内存 (operator new) 2. 调用构造函数。它并不在创建时检查析构函数的访问权限。
delete操作符会调用析构函数,因此我们必须提供一个公有的销毁方法来执行 delete this,这个方法必须是类的成员函数或友元
class DynamicOnly {
public:
// 1. 公有构造函数
DynamicOnly() {
std::cout << "DynamicOnly constructor\n";
}
// 2. 提供公有的销毁方法,代替析构函数
void destroy() {
delete this; // 在类内部,可以调用私有析构函数
}
// 3. 可选:提供一个静态的创建方法,更规范
static DynamicOnly* create() {
return new DynamicOnly();
}
protected:
// 4. 关键:将析构函数设为protected或private
~DynamicOnly() {
std::cout << "DynamicOnly destructor\n";
}
};
// 使用方式
int main() {
// DynamicOnly obj1; // 错误:析构函数不可访问,无法在栈上创建
// DynamicOnly* obj2 = new DynamicOnly();
// delete obj2; // 错误:析构函数不可访问,无法直接delete
DynamicOnly* obj = DynamicOnly::create(); // 正确:在堆上创建
obj->destroy(); // 正确:通过公有方法销毁
// 或者: obj->destroy();
}
只能静态分配(只能在栈上创建)
核心思想:将 operator new和 operator delete重载为 private或使用 = delete。
为什么?
使用 new表达式创建对象时,会先调用 operator new分配内存,再调用构造函数。
如果 operator new是不可访问的,new表达式就会编译失败,从而阻止其在堆上创建。
析构函数必须是公有的,以便栈对象离开作用域时能正常被调用。
class StaticOnly {
public:
StaticOnly() {
std::cout << "StaticOnly constructor\n";
}
~StaticOnly() { // 公有析构函数
std::cout << "StaticOnly destructor\n";
}
private:
// 1. 将operator new设为私有,阻止new表达式
void* operator new(size_t size) {
return ::operator new(size);
}
void* operator new[](size_t size) {
return ::operator new[](size);
}
// 2. 同样需要禁止placement new(可选但推荐)
void* operator new(size_t, void* ptr) = delete;
void* operator new[](size_t, void* ptr) = delete;
// 3. 对应的operator delete也设为私有
void operator delete(void* ptr) {
::operator delete(ptr);
}
void operator delete[](void* ptr) {
::operator delete[](ptr);
}
};
// 使用方式
int main() {
StaticOnly obj; // 正确:在栈上创建
// StaticOnly* p = new StaticOnly(); // 错误:operator new是私有的
}
2005

被折叠的 条评论
为什么被折叠?



