Предположим, что такой класс:
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 ++?
Обычным решением является использование 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
функция закрывает файл, и
если завершение завершается успешно, устанавливает флаг, что файл был
совершено. Деструктор проверяет флаг, и если файл
не было совершено, оно закрывает а также удаляет его, так что нет
частичный файл остается лежать вокруг.
Следующий код в целом похож:
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 ++ имеют деструкторы, которые можно использовать для выполнения любой очистки.