是否可以阻止对象的堆栈分配,并且只允许在堆上使用'new'来填充它?
答案 0 :(得分:82)
你可以做到这一点的一种方法是使构造函数变为私有,只允许通过返回指针的静态方法进行构造。例如:
class Foo
{
public:
~Foo();
static Foo* createFoo()
{
return new Foo();
}
private:
Foo();
Foo(const Foo&);
Foo& operator=(const Foo&);
};
答案 1 :(得分:16)
对于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();
};
答案 2 :(得分:11)
您可以创建构造函数private
,然后提供public
静态工厂方法来创建对象。
答案 3 :(得分:5)
以下允许公共构造函数,并通过在运行时抛出来停止堆栈分配。注意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;
答案 4 :(得分:0)
在C ++ 20中使用销毁运算符delete应该可以实现这一点,请参见p0722r3。
#include <new>
class C
{
private:
~C() = default;
public:
void operator delete(C *c, std::destroying_delete_t)
{
c->~C();
::operator delete(c);
}
};
请注意,私有析构函数可防止将其用于动态存储持续时间以外的任何时间。但是销毁运算符delete允许通过delete表达式销毁它(因为在这种情况下delete表达式不会隐式调用析构函数)。
答案 5 :(得分:-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;
}