В новостной группе я несколько раз встречал вопросы подобного плана, указывающие на недостаток понимания работы экземпляра объекта. Я понимаю, что данный вопрос могут задать скорее новички в программировании, поэтому свой рассказ я начну издалека - с организации классов в Delphi. Я надеюсь, что моя "попытка" ликбеза по крайней мере объяснит суть предмета.
Во всяком случае, рекомендую данный материал для всех, кто хоть раз сталкивался с ошибками указателей, исключительными ситуациями и GPF.
Когда вы объявляете переменную некоторого типа класса, как например...
var MyVar: TMyClass; |
....всех вас интересует: что делает в этом случае компилятор и достаточно ли распределено памяти, чтобы хранить указатель на экземпляр данного класса в куче памяти. Знайте же: вы не распределили память для данного класа, вы только что распределили память для указателя. Компилятор всегда инициализирует этот указатель в $FFFFFFFF, а это значит, что распределенный блок памяти пуст. Во всяком случае этого достаточно, чтобы сказать что указатель *не* указывает на верную "позицию" памяти и ваш класс *не* содержит никаких данных.
Delphi распределит и заполнит память за вас, но и вы должны немного потрудиться. Когда вы используете один из классов Delphi или свой собственный, вы должны создать его экземпляр. Что это значит: вы должны распределить память и установить на распределенный блок памяти указатель. В некоторых языках это выглядит безобразно, в Delphi же это выглядит так...
MyVar := TMyClass.Create; |
Это действительно просто, поскольку метод конструктора Create класса TMyClass является классовым методом - он работает в классе, а не в отдельном объекте. Когда вы вызываете конструктор, Delphi распределяет память и возвращает значение указателя. Присмотритесь: не похоже ли это на вызов функции? Хорошо, если вы раньше не знали, что возвращалось при вызове, то теперь вы это знаете. Вызов TMyClass.Create возвращает указатель на объект типа TMyClass.
В конце концов то, что вам действительно нужно помнить, это...
procedure Example; var MyObj: TMyClass; // класс, который вы создаете MyList: TList; // встроенный класс begin MyObj := TMyClass.Create; // теперь MyObj содержит адрес блока памяти, распределенной для экземпляра вашего класса MyList := TList.Create; // Код для работы с MyList .... здесь что-то делаем с объектом .... MyList.Free; // Ресурсы MyList удаляются из кучи MyObj.Free; // тоже самое для MyObj end; |
[000312]