【发布时间】:2021-12-09 10:28:34
【问题描述】:
我想我会深入研究一下捕获异常。
根据这个问题 (C++ catching all exceptions) 的答案之一是:
[
catch(...)] 将捕获所有 C++ 异常,但它应该被视为糟糕的设计。
目前我已经使用了这种方法:
CPTSDatabase::~CPTSDatabase()
{
try
{
CloseDatabase();
}
catch(...)
{
}
}
void CPTSDatabase::CloseDatabase()
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
我认为这是正确的方法,因为当我追踪到 CDatabase::Close() 时,它会执行类似的操作:
// Disconnect connection
void CDatabase::Close()
{
ASSERT_VALID(this);
// Close any open recordsets
AfxLockGlobals(CRIT_ODBC);
TRY
{
while (!m_listRecordsets.IsEmpty())
{
CRecordset* pSet = (CRecordset*)m_listRecordsets.GetHead();
pSet->Close(); // will implicitly remove from list
pSet->m_pDatabase = NULL;
}
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_ODBC);
THROW_LAST();
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_ODBC);
if (m_hdbc != SQL_NULL_HDBC)
{
RETCODE nRetCode;
AFX_SQL_SYNC(::SQLDisconnect(m_hdbc));
AFX_SQL_SYNC(::SQLFreeConnect(m_hdbc));
m_hdbc = SQL_NULL_HDBC;
_AFX_DB_STATE* pDbState = _afxDbState;
AfxLockGlobals(CRIT_ODBC);
ASSERT(pDbState->m_nAllocatedConnections != 0);
pDbState->m_nAllocatedConnections--;
AfxUnlockGlobals(CRIT_ODBC);
}
}
CDatabase::Close 文档甚至没有说明任何关于抛出异常的信息。
链接的答案确实说明:
可以使用c++11新的
current_exception机制。
鉴于我们正在使用的CDatabase 类,我们是否可以使用这种方法尚不清楚。
【问题讨论】:
-
在一个不相关的注释上,
CDatabase::Close()完全做了其他事情。它实现了在 Java 或 C# 等语言中常见的try/finally模式。它允许标记需要运行的代码区域,无论是否引发异常。释放锁肯定是你一直希望发生的事情,这就是整个 try-catch-unlock-rethrow 舞蹈正在做的事情。如果今天重新实现 MFC,它只需使用 scoped_lock,所有 try-catch-rethrow 噪音都会神奇地消失。
标签: c++ exception visual-c++ mfc cdatabase