лекции (2003) (Глазкова) (1160821), страница 26
Текст из файла (страница 26)
Т.е. общая проблема (проблема инициализации) полностью решена с помощью понятия конструктора. Однако, как только в языке появляется автоматическая сборка мусора, появляется необходимость явного вызова функции, которая освобождала бы ресурсы.
В языке С++ есть простая и хорошая схема работы с ресурсами. Для каждого ресурса заводится cвой класс CResourse. В конструкторе этого класса происходит захват ресурса, а в деструкторе происходит освобождение ресурса:
CResourse () {захват ресурса}
~ CResourse () {освобождение ресурса}
Как только нет автоматического вызова деструктора при выходе блока (а это происходит в языках с автоматической сборкой мусора – Java, C#), схема работы с ресурсами языка С++ не годится. Каким же образом в этих языках организована схема работы с ресурсами? В этих языках появляется специальный оператор try {…} finally {…}.
Гарантируется, что код finally-блока будет исполнен всегда.
Выход из try блока может быть нормальный (по закрывающей скобке или оператору return) или ненормальный (по возбуждению исключения, т.е. аварийной ситуации).
В любом случае код в finally-блоке будет исполнен всегда.
Поэтому в языках с автоматической сборкой мусора (и вообще во всех языках со ссылочной структурой) общая схема работы с ресурсом следующая:
захват ресурса
try{
работа с ресурсом
} finally {освобождение ресурса}
Это сделано для того, чтобы унифицировать работу с ресурсами.
Если класс захватывает ресурсы, не связанные с динамической памятью, надо написать функцию освобождения этих ресурсов и явно её вызывать.
Заметим, что в языках Java, Delphi, C# понятие конструктора копирования отсутствует, потому что отсутствует проблема копирования (когда речь идет о копировании объектов, это просто копирование ссылок; а если надо глубинное копирование используется метод clone( ); )
Если мы хотим запретить копирование объектов в С++, надо явно определить конструктор копирования, операцию присваивания, и сделать ее приватной (тогда извне обращение будет запрещено).
В языке Java, С#, если мы хотим запретить операцию копирования объекта, мы переопределяем clone() так, чтобы запретить создание глубинных копий объекта (при попытке глубинного копирования, ошибка будет не на этапе компиляции, а на этапе выполнения).
В языке Java пользовательские неявные преобразования запрещены, поэтому понятие конструктора преобразования и оператора преобразования отсутствует. Тем самым семантика языка существенно упрощается.
В языке С# конструктор копирования отсутствует по определению; из всех конструкторов существует только конструктор умолчания, который неявно вызывается только в том случае, если неявно вызывается конструктор умолчании базового класса.
Вместо ключевого слова Super в Java используется ключевое слово inherited.
В языке С# неявные преобразования разрешены, потому что С# пытается занять достаточно широкую экологическую нишу.
В языке С# роль глобальных функций выполняют статические функции – члены класса.
В отличии от С++, для неявных преобразований в языке С# употребляются только операторы преобразования, при этом они выступают как статические функции – члены какого-либо класса.
Пример.
Class X{
……….
public static operator T (X obj) {….}
………
}
Заметим, что здесь класс Х выступает исключительно как модуль, внутри которого хранится статическая функция – оператор преобразования.
В качестве Т и Х могут выступать только классы: нельзя писать преобразования из стандартных типов в пользовательские и обратно. Такие преобразования запрещены, потому что существует единая система типов CTS (Common Type System), которая определяет семантику стандартных типов. Никакой пользовательской семантики к этим типам добавлять нельзя.
В С# есть два слова: explicit и implicit,
По умолчанию – explicit.
Эти ключевые слова управляют тем, как интерпретируется оператор преобразования.
Если explisit - оператор можно вызывать только явно.
Форма вызова:
T t;
X a;
t=X.operator T(a);
Если же implicit – то этот код подставляется неявно.
Пример. T t;
X a;
t=a; // t=(T)a;
Осталось поговорить про язык Delphi и специальный класс функций, который называется свойствами.
113