c++ c++-faq

c++ - ¿Es posible evitar la asignación de apilamiento de un objeto y solo permitir que se lo instancia con ''nuevo''?



c++-faq (5)

Puede crear un archivo de encabezado que proporcione una interfaz abstracta para el objeto y funciones de fábrica que devuelvan punteros a objetos creados en el montón.

// 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; }

¿Es posible evitar la asignación de pila de un objeto y solo permitir que se inicie con ''nuevo'' en el montón?


Puede hacer que el constructor sea private y luego proporcionar un método public fábrica estático para crear los objetos.


Una forma de hacerlo podría consistir en hacer que los constructores sean privados y solo permitir la construcción a través de un método estático que devuelva un puntero. Por ejemplo:

class Foo { public: ~Foo(); static Foo* createFoo() { return new Foo(); } private: Foo(); Foo(const Foo&); Foo& operator=(const Foo&); };


En el caso de 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(); };


Lo siguiente permite constructores públicos y detendrá las asignaciones de pila lanzando en tiempo de ejecución. Nota thread_local es una palabra clave 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;