C++, препятствуя тому, чтобы экземпляр класса был создан на стеке (во время compiltaion)

Я знаю, что существуют методы, чтобы препятствовать тому, чтобы класс был создан на "куче", препятствуя тому, чтобы пользователь использовал new и delete оператор. Я пытаюсь сделать совсем противоположное. У меня есть класс, что я хочу препятствовать тому, чтобы пользователь создал экземпляр его на стеке, и что только экземпляры спровоцировали использование new оператор скомпилирует. Строго говоря, я хочу, чтобы следующий код получил ошибку во время компиляции:

MyClass c1; //compilation error

MyClass* c1 = new MyClass(); //compiles okay

От поиска сети я нашел это предложение о том, как сделать это:

class MyClass {
public:
    MyClass();
private:
    void destroy() const { delete this; }

...

private:
    ~MyClass();
};

int main(int argc,char** argv)
{
    MyClass myclass; // <--- error, private destructor called here !!!

    MyClass* myclass_ptr = new MyClass;
    myclass_ptr->destroy();
}

То, что я не понимаю, - то, почему это должно работать. Почему деструктор назвали бы при создании экземпляра MyClass?

8
задан GntS 6 December 2016 в 10:04
поделиться

5 ответов

Когда myclass достигает конца своей области (следующего } ), компилятор вызывает деструктор, чтобы освободить его из стека. Однако, если деструктор является частным, доступ к деструктору невозможен, поэтому класс не может быть помещен в стек.

Мне не нравится вид удалить . В общем, я считаю, что объекты не должны разрушаться сами по себе. Возможно, лучший способ - иметь частный конструктор для вашего класса, а затем использовать статическую функцию для создания экземпляра.

// In class declaration...
static MyClass* Create()
{
    return new MyClass(); // can access private constructor
}

// ...

MyClass myclass; // illegal, cannot access private constructor

MyClass* pMyClass = MyClass::Create();
delete pMyClass; // after usage
23
ответ дан 5 December 2019 в 04:54
поделиться

Когда локальная переменная выходит за пределы области видимости, она уничтожен. И при уничтожении вызывается деструктор объекта. Здесь основная функция - это объем. При выходе из программы вызывается деструктор объекта myclass

1
ответ дан 5 December 2019 в 04:54
поделиться

Нет. Компилятор пытается вызвать деструктор, когда он выходит за пределы области видимости, и указывает на строку кода, которая производит этот эффект, что гораздо полезнее, чем указание на конец функции.

1
ответ дан 5 December 2019 в 04:54
поделиться

Потому что, когда экземпляр выходит за пределы области видимости, он должен быть уничтожен с помощью деструктора. Указатель на экземпляр этого не делает.

1
ответ дан 5 December 2019 в 04:54
поделиться

Почему деструктор должен вызываться при создании экземпляра MyClass?

Это не так. Однако он должен вызываться автоматически, когда экземпляр выходит из области видимости. Если он приватный, компилятор не должен генерировать этот код, отсюда и ошибка.

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

class MyClass {
public:
  static MyClass* create()             {return new MyClass();}
  static MyClass* create(const Foo& f) {return new MyClass(f);}
private:
  MyClass();
  MyClass(const Foo&);
};

Обратите внимание, что возвращение голых указателей на объекты, которые должны быть удалены, не одобряется. Вместо этого следует возвращать умные указатели:

class MyClass {
public:
  static std::shared_ptr<MyClass> create()             {return new MyClass();}
  static std::shared_ptr<MyClass> create(const Foo& f) {return new MyClass(f);}
  // ...
};
12
ответ дан 5 December 2019 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: