@ DK, Следует отметить, что в C ++ (и Java, я думаю) вы могли бы легко использовать "анонимный" класс для достижения того же, что и видимость (выход):
int some_func()
{
class _dbguard { sqlite3* db;
_dbguard(const _dbguard&); _dbguard& operator=(const _dbguard&);
public:
_dbguard(const char* dbname) { sqlite3_open(dbname, &db);}
~_dbguard() {sqlite3_close(db);}
operator sqlite3*() { return db; }
} db("dbname");
...
}
И если бы вы делали это не раз, вы бы сразу превратили его в полный класс, чтобы обработать ваш RAII для вас. Это так просто написать, я не могу представить программу на C ++, которая использует sqlite (как используется в примере) без создания классов, таких как CSqlite_DB и CSqlite_Stmt. На самом деле оператор sqlite3 * () должен быть анафамным, а в полной версии будут просто методы, предоставляющие операторы:
class CSqlite3_DB {
...
CSqlite3_Stmt Prepare(const std::string& sql) {
sqlite3_stmt* stmt = 0;
try {
sqlite3_prepare_v2(db, sql.c_str(), &stmt);
} catch (...) {}
return stmt;
}
};
Что касается исходного вопроса, я бы сказал, что ответ «не совсем». Надлежащее уважение к DRY скажет вам взять эти длинные блоки try / catch / finally и преобразовать их в отдельные классы, которые скрывают части try / catch от остальных, где они могут (в случае области видимости (сбой)), и делают прозрачное управление ресурсами (в случае области (выход)).