Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Можно ли сделать так, чтобы объект класса создавался только путём выделения памяти в куче, а не на стеке?

#cpp #классы


MyClass o; // error
MyClass * o = new MyClass; // ok

    


Ответы

Ответ 1



Конечно, можно. Закройте его деструктор (сделайте его private). Чтобы удалить выделенный динамически объект, вам придется написать отдельную функцию - например, друга или статический член - для удаления, вроде friend void destroy(MyClass* t) { delete t; } ... MyClass * o = new MyClass; ... destroy(o);

Ответ 2



Если в первую очередь имеет значение сам факт создания в куче, и нет обязательного требования разрешать в клиентском коде запись вида new MyClass, то вместо сокрытия деструктора можно подойти с другой стороны жизненного цикла объекта и сделать приватным конструктор, предоставив соответствующую create-функцию или даже семейство функций: class MyClass { MyClass(); public: static MyClass* create() { return new MyClass; } }; Теперь, чтобы не забыть сделать delete объекта в нужный момент и не получить утечку памяти, разумно возвращать не сырой указатель, а std::unique_ptr. Функция изменится так: static std::unique_ptr create() { return std::unique_ptr(new MyClass); } Однако, если мы пойдём ещё дальше и заменим std::unique_ptr(new MyClass) на std::make_unique() для уменьшения накладных расходов, то получим ошибку компиляции: error: calling a private constructor of class 'MyClass' Возникает это из-за того, что мы пытаемся вызвать наш приватный конструктор по сути вне класса MyClass. Но это можно побороть следующим небольшим "хаком" - добавить приватный тип и использовать его в качестве дополнительного параметра для конструктора MyClass, при этом сам конструктор снова сделать публичным. Итоговый пример: class MyClass { class tag {}; // скрытый от внешнего кода тип public: MyClass(const tag&) {} static std::unique_ptr create() { return std::make_unique(tag()); } }; int main() { auto p = MyClass::create(); }

Комментариев нет:

Отправить комментарий