是否可以防止对象的堆栈分配并只允许在堆上使用“new”来启动它?
Joseph
问问题
13161 次
6 回答
86
您可以这样做的一种方法是将构造函数设为私有,并且只允许通过返回指针的静态方法进行构造。例如:
class Foo
{
public:
~Foo();
static Foo* createFoo()
{
return new Foo();
}
private:
Foo();
Foo(const Foo&);
Foo& operator=(const Foo&);
};
于 2008-09-24T01:32:04.497 回答
23
在 C++11 的情况下
class Foo
{
public:
~Foo();
static Foo* createFoo()
{
return new Foo();
}
Foo(const Foo &) = delete; // if needed, put as private
Foo & operator=(const Foo &) = delete; // if needed, put as private
Foo(Foo &&) = delete; // if needed, put as private
Foo & operator=(Foo &&) = delete; // if needed, put as private
private:
Foo();
};
于 2012-10-02T20:07:19.110 回答
12
您可以制作构造函数private
,然后提供public
静态工厂方法来创建对象。
于 2008-09-24T01:31:50.443 回答
6
以下允许公共构造函数,并将通过在运行时抛出来停止堆栈分配。注意thread_local
是 C++11 关键字。
class NoStackBase {
static thread_local bool _heap;
protected:
NoStackBase() {
bool _stack = _heap;
_heap = false;
if (_stack)
throw std::logic_error("heap allocations only");
}
public:
void* operator new(size_t size) throw (std::bad_alloc) {
_heap = true;
return ::operator new(size);
}
void* operator new(size_t size, const std::nothrow_t& nothrow_value) throw () {
_heap = true;
return ::operator new(size, nothrow_value);
}
void* operator new(size_t size, void* ptr) throw () {
_heap = true;
return ::operator new(size, ptr);
}
void* operator new[](size_t size) throw (std::bad_alloc) {
_heap = true;
return ::operator new[](size);
}
void* operator new[](size_t size, const std::nothrow_t& nothrow_value) throw () {
_heap = true;
return ::operator new[](size, nothrow_value);
}
void* operator new[](size_t size, void* ptr) throw () {
_heap = true;
return ::operator new[](size, ptr);
}
};
bool thread_local NoStackBase::_heap = false;
于 2013-11-20T02:59:23.347 回答
2
这应该可以在 C++20 中使用破坏运算符删除,请参阅p0722r3。
#include <new>
class C
{
private:
~C() = default;
public:
void operator delete(C *c, std::destroying_delete_t)
{
c->~C();
::operator delete(c);
}
};
请注意,私有析构函数会阻止它用于动态存储持续时间以外的任何其他用途。但是销毁操作符 delete 允许通过删除表达式将其销毁(因为在这种情况下,删除表达式不会隐式调用析构函数)。
于 2018-08-22T17:14:07.450 回答
-1
您可以创建一个为对象提供抽象接口的头文件,以及返回指向在堆上创建的对象的指针的工厂函数。
// Header file
class IAbstract
{
virtual void AbstractMethod() = 0;
public:
virtual ~IAbstract();
};
IAbstract* CreateSubClassA();
IAbstract* CreateSubClassB();
// Source file
class SubClassA : public IAbstract
{
void AbstractMethod() {}
};
class SubClassB : public IAbstract
{
void AbstractMethod() {}
};
IAbstract* CreateSubClassA()
{
return new SubClassA;
}
IAbstract* CreateSubClassB()
{
return new SubClassB;
}
于 2008-09-24T01:37:39.837 回答