В Java 7 Вы не должны закрывать их явно, но использование автоматическое управление ресурсами , чтобы гарантировать, что ресурсы закрываются, и исключения обработаны соответственно. Обработка исключений работает как это:
Exception in try | Exception in close | Result -----------------+--------------------+---------------------------------------- No | No | Continue normally No | Yes | Throw the close() exception Yes | No | Throw the exception from try block Yes | Yes | Add close() exception to main exception | | as "suppressed", throw main exception
, Надо надеяться, который имеет смысл. В позволяет симпатичный код, как это:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
До Java 7, лучше использовать вложенный наконец блоки, вместо того, чтобы тестировать ссылки на пустой указатель.
пример, который я покажу, мог бы выглядеть ужасным с глубоким вложением, но на практике, хорошо разработанный код, вероятно, не собирается создавать соединение, оператор и результаты все в том же методе; часто, каждый уровень вложения включает передачу ресурса к другому методу, который использует его в качестве фабрики для другого ресурса. С этим подходом исключения из close()
замаскируют исключение изнутри try
блок. Это может быть преодолено, но это приводит к еще более грязному коду и требует пользовательского класса исключений, который обеспечивает "подавленное" объединение в цепочку исключения, существующее в Java 7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
Самый простой способ - сделать счетчик ссылок изменяемым.
Однако, если вас интересует, как он будет работать с const_cast
, тогда переопределите boost remove_const
должно быть довольно простым:
template <class T>
struct RemoveConst
{
typedef T type;
};
template <class T>
struct RemoveConst<const T>
{
typedef T type;
};
const_cast<typename RemoveConst<T>::type*>(t)->inc();
У вас есть ответ. const_cast работает в обоих направлениях:
char* a;
const char* b;
a = const_cast<char*>(b);
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration
Что касается конкретной проблемы, рассматривали ли вы ключевое слово mutable? Он позволяет изменять переменную-член внутри метода const.
class foo {
mutable int x;
public:
inc_when_const() const { ++x; }
dec_when_const() const { --x; }
};
Сделайте счетчик ссылок изменяемым в классе, управляемом вашим навязчивым указателем. Это вполне разумно и точно отражает «логическую константность» - то есть изменение счетчика ссылок на объект не отражает никаких изменений в состоянии самого объекта. Другими словами, счетчик ссылок логически не является частью объекта - объект просто оказывается удобным местом для хранения этих полунезависимых данных.
Если вы можете использовать Boost, библиотека Type Traits предоставляет метафункцию remove_const , которая делает это.