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

346
05 декабря 2017, 21:23
MyClass o; // error
MyClass * o = new MyClass; // ok
Answer 1

Конечно, можно. Закройте его деструктор (сделайте его private).

Чтобы удалить выделенный динамически объект, вам придется написать отдельную функцию - например, друга или статический член - для удаления, вроде

friend void destroy(MyClass* t) { delete t; }
...
MyClass * o = new MyClass;
...
destroy(o);
Answer 2

Если в первую очередь имеет значение сам факт создания в куче, и нет обязательного требования разрешать в клиентском коде запись вида new MyClass, то вместо сокрытия деструктора можно подойти с другой стороны жизненного цикла объекта и сделать приватным конструктор, предоставив соответствующую create-функцию или даже семейство функций:

class MyClass {
    MyClass();
public:  
    static MyClass* create() { return new MyClass; }
};

Теперь, чтобы не забыть сделать delete объекта в нужный момент и не получить утечку памяти, разумно возвращать не сырой указатель, а std::unique_ptr. Функция изменится так:

static std::unique_ptr<MyClass> create() { return std::unique_ptr<MyClass>(new MyClass); }

Однако, если мы пойдём ещё дальше и заменим std::unique_ptr<MyClass>(new MyClass) на std::make_unique<MyClass>() для уменьшения накладных расходов, то получим ошибку компиляции:

error: calling a private constructor of class 'MyClass'

Возникает это из-за того, что мы пытаемся вызвать наш приватный конструктор по сути вне класса MyClass. Но это можно побороть следующим небольшим "хаком" - добавить приватный тип и использовать его в качестве дополнительного параметра для конструктора MyClass, при этом сам конструктор снова сделать публичным. Итоговый пример:

class MyClass {
    class tag {}; // скрытый от внешнего кода тип
public:
    MyClass(const tag&) {}      
    static std::unique_ptr<MyClass> create() { return std::make_unique<MyClass>(tag()); }
};
int main() {
    auto p = MyClass::create();
}
READ ALSO
Обрубка русского текста

Обрубка русского текста

Пытаюсь вывести предложение с указанным искомым словом, но программа не выводит полностью всё предложение, а лишь часть текста

224
Многооконное приложение в QML

Многооконное приложение в QML

Добрый деньИмеется основная форма (ApplicationWindow), на которой есть активный элемент

282
boost::variant boost::apply_visitor

boost::variant boost::apply_visitor

Как используется boost::variant (в частности apply_visitor)?

234