Выполнена глава 3 «Обработка исключений и ошибок», отрывок.
Конструкторы и исключения
Эта тема часто упоминается в сообществе C++, но в сообществе Delphi, похоже, никто не обратил на нее внимания. Возможно, из-за особенностей языка программистам Delphi не нужно беспокоиться по этому поводу. Но я думаю, что программисты Delphi также должны понимать эту проблему и знать, что дает нам язык, чтобы нам было так легко ее игнорировать. Как говорится: «Когда тебя окружают благословения, ты должен знать эти благословения». Мы знаем, что конструктор класса не имеет возвращаемого значения. Если конструктору не удается создать объект, невозможно рассчитывать на возврат кода ошибки. Итак, как выявить неисправность конструктора в программе? Самый «стандартный» метод: создать исключение. Сбой конструктора означает, что конструкция объекта не удалась. Итак, как будет обрабатываться этот «полумертвый» объект после того, как будет выдано исключение? Здесь, я думаю, перед чтением необходимо иметь представление о том, как C++ справляется с этой ситуацией. В C++ деструктор не вызывается после того, как конструктор выдает исключение. Такой подход разумен, поскольку на данный момент объект еще не полностью построен. Если конструктор выполнил некоторые операции, такие как выделение памяти, открытие файлов и т. д., то класс C++ должен иметь свои собственные члены, чтобы запоминать, какие действия были выполнены. Конечно, это очень хлопотно для разработчиков классов, поэтому обычно разработчики классов C++ избегают создания исключений в конструкторах (вы можете предоставить функции-члены, такие как Init и UnInit, которые оставляются на усмотрение конструктора или клиента класса. Они вызываются для обработки). сбой инициализации). Решение, представленное в каждой классической книге по C++, заключается в использовании интеллектуальных указателей (стандартный класс STL auto_ptr). В Object Pascal эта проблема становится очень простой, и программистам не нужно об этом беспокоиться. Если класс Object Pascal выдаст исключение в конструкторе, компилятор автоматически вызовет деструктор класса (поскольку деструктор не может быть перегружен, гарантируется, что существует только один деструктор, поэтому компилятор не запутается . среди нескольких деструкторов). Объекты-члены обычно разрушаются в деструкторе, а метод Free() гарантирует, что деструктор не будет вызываться для нулевых объектов (то есть объектов-членов, которые еще не созданы). Поэтому, делая код кратким и красивым, это также обеспечивает безопасность. type MyClass = classPRivateFStr : PChar; // Указатель строки publicconstructor Create();destructor Destroy(); end;constructor MyClass.Create();beginFStr := StrAlloc(10); // Указатель строки в конструкторе Allocate MemoryStrCopy( FStr, 'ABCDEFGHI'); вызвать Exception.Create('ошибка'); Выдача исключения без причины, hahaend;деструктор A.Destroy();beginStrDispose(FStr); // Освобождение памяти в деструкторе WriteLn('Free Resource');end;varObj : TMyClass;i : целое;begintryObj : = TMyClass.Create; ();Obj.Free();WriteLn('Успешно');кромеObj := nil;WriteLn('Failed');end;Read(i); // Приостановите экран, чтобы увидеть завершение результатов выполнения. В этом коде конструктор генерирует исключение, и результат выполнения: Free ResourceFailed in this time" Вывод Free Resource» создается компилятором, автоматически вызывающим деструктор. Поэтому, если документация класса или автор класса говорят вам, что конструктор класса может выдать исключение, не забудьте обернуть его с помощью try...кроме! Различные способы обработки исключений, создаваемых конструкторами, в C++ и Object Pascal на самом деле являются воплощением дизайнерских идей этих двух языков. C++ придерживается стиля C и ориентирован на эффективность. Все остается на усмотрение программиста, и компилятор не совершает лишних действий. Object Pascal наследует стиль Паскаля и фокусируется на эстетическом значении программы. Компилятор помогает программистам выполнять сложную работу.