try catch — C ++, как безопасно закрыть файл без try {} finally {}?

Предположим, что такой класс:

class A {
private:
QFile file;

public:
A::A(QFile file): file(file) {}

void doSomething() {
file.open(QIODevice::WriteOnly);
// ... do operations that can throw an exception
file.close();
}
}

если что-то происходит, close () никогда не вызывает его. Правильно будет использовать try — finally, но C ++ не поддерживает его:

class A {
private:
QFile file;

public:
A::A(QFile file): file(file) {}

void doSomething() {
file.open(QIODevice::WriteOnly);
try {
// ... do operations that can throw an exception
}
finally {
file.close();
}
}
}

Как я могу сделать это на C ++?

0

Решение

Обычным решением является использование RAII: в этом случае, например, если
QFile имеет «правильный» деструктор, просто объявив его как локальный
переменная должна сделать свое дело:

void A::doSomething()
{
QFile file;
file.open(...);
//  ...
file.close();   //  So you can check that everything when right.
}

Файл должен автоматически закрываться, когда QFile является
разрушен, хотя, если он не был закрыт раньше, вы не будете
возможность проверить состояние (и данные в файле могут быть
неполный).

Если по какой-либо причине это невозможно, вы можете использовать
класс оболочки с областью действия:

class QFileWrapper
{
QFile* myFile;
public:
QFileWrapper( QFile* file ) : myFile( file ) {}
~QFileWrapper() { myFile->close(); }
};

На самом деле я делаю это много для std::ofstreamс commit
функция, и это конструктор, который принимает имя файла,
и делает открытое. commit функция закрывает файл, и
если завершение завершается успешно, устанавливает флаг, что файл был
совершено. Деструктор проверяет флаг, и если файл
не было совершено, оно закрывает а также удаляет его, так что нет
частичный файл остается лежать вокруг.

3

Другие решения

Следующий код в целом похож:

try {
/*do something that may throw an exception*/
} catch (.../*the ellipsis means catch anything*/){
/* any cleanup */
throw; /*this rethrows the exception, not compulsory to include*/
}

Это не совсем то же самое, так как блок catch будет введен только в случае возникновения исключения (в отличие от finally блок в Java).

Но C ++ не необходимость finally конструкция, так как объекты C ++ имеют деструкторы, которые можно использовать для выполнения любой очистки.

0

По вопросам рекламы [email protected]