Бьерн Страуструп.
Язык программирования С++
244
перехватываются все особые ситуации, закрывается файл и особая ситуация запускается повторно.
Недостаток этого решения в
его многословности, громоздкости и потенциальной расточительности. К
тому же всякое многословное и громоздкое решение чревато ошибками, хотя бы в силу усталости
программиста. К счастью, есть более приемлемое решение. В
общем виде проблему можно
сформулировать так:
void acquire()
{
// запрос ресурса 1
//
...
// запрос ресурса n
// использование ресурсов
// освобождение ресурса n
//
...
// освобождение ресурса 1
}
Как правило бывает важно, чтобы ресурсы освобождались в обратном по сравнению с запросами
порядке. Это
очень сильно напоминает порядок работы с локальными объектами, создаваемыми
конструкторами и уничтожаемыми деструкторами. Поэтому мы можем решить
проблему запроса и
освобождения ресурсов, если будем использовать подходящие объекты классов с конструкторами и
деструкторами. Например, можно определить класс FilePtr, который выступает как тип FILE* :
class FilePtr {
FILE*
p;
public:
FilePtr(const char* n, const char* a)
{ p = fopen(n,a); }
FilePtr(FILE* pp) { p = pp; }
~FilePtr()
{
fclose(p);
}
operator FILE*() { return p; }
};
Построить объект FilePtr можно либо, имея объект типа FILE*, либо, получив нужные для fopen()
параметры. В любом случае этот объект будет уничтожен при выходе из его области видимости, и его
деструктор закроет файл. Теперь наш пример сжимается до такой функции:
void use_file(const char* fn)
{
FilePtr
f(fn,"w");
// работаем с f
}
Деструктор будет вызываться независимо от того, закончилась ли
функция нормально, или произошел
запуск особой ситуации.
Достарыңызбен бөлісу: