Я знаю, что существуют методы, чтобы препятствовать тому, чтобы класс был создан на "куче", препятствуя тому, чтобы пользователь использовал 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
?
Когда 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
Когда локальная переменная выходит за пределы области видимости, она уничтожен. И при уничтожении вызывается деструктор объекта. Здесь основная функция - это объем. При выходе из программы вызывается деструктор объекта myclass
Нет. Компилятор пытается вызвать деструктор, когда он выходит за пределы области видимости, и указывает на строку кода, которая производит этот эффект, что гораздо полезнее, чем указание на конец функции.
Потому что, когда экземпляр выходит за пределы области видимости, он должен быть уничтожен с помощью деструктора. Указатель на экземпляр этого не делает.
Почему деструктор должен вызываться при создании экземпляра
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);}
// ...
};