Я узнал, что если выброс из программы-деструктора будет прерван, если это произойдет во время разматывания стека, потому что тогда будет распространяться более 1 исключения.
Вот пример с комментарием, который демонстрирует это:
class Foo
{
public:
~Foo()
{
ReleaseResources();
}
private:
int* pInt;
void ReleaseResources()
{
if (!pInt)
throw 0;
else delete pInt;
}
};
int main() try
{
{
Foo local;
throw 1;
} // aborting here, because now 2 exceptions are propagating!
return 0;
}
catch (int& ex)
{
return ex;
}
Однако у меня есть иерархия классов, где один из деструкторов вызывает функцию, которая может генерировать, и из-за этой иерархии записей это отравлено, что означает, что теперь все деструкторы помечены как noexcept(false)
.
, в то время какэто нормально для компилятора, чтобы вставить код исключения, это не нормально для пользователя этих классов, потому что это не предотвращает прерывание программы, если происходит пример сценария из приведенного выше кода.
Потому что я хочу, чтобы деструкторы были безопасными для исключенияЯ пришел к мысли, чтобы пометить их все как noexcept
, но обработать возможные исключения внутри деструктора следующим образом:
Тот же пример, но переработанный так, что прерывание невозможно, а исключение деструкторов безопасно:
class Foo
{
public:
~Foo() noexcept
{
try
{
ReleaseResources();
}
catch (int&)
{
// handle exception here
return;
}
}
private:
int* pInt;
void ReleaseResources()
{
if (!pInt)
throw 0;
else delete pInt;
}
};
int main() try
{
{
Foo local;
throw 1;
} // OK, not aborting here...
return 0;
}
catch (int& ex)
{
return ex;
}
Вопрос в том, является ли этот нормальный подход обработкой исключений внутриrucotrs? Есть ли примеры, которые могли бы заставить этот дизайн пойти не так?
Основная цель - создать безопасные деструкторы исключений.
Также побочный вопрос, во втором примере, во время разматывания стека, еще есть 2распространяются исключения, как это не прерывается? разрешено ли только одно исключение при разматывании стека?