Я компилирую библиотеку C++, и у меня есть проблема с деструкторами и noexcept
.Исключение броска в деструкторе производного класса
Это мое понимание, что, поскольку C++ 11, значение по умолчанию noexcept(...)
внутри деструкторов изменилось. В частности, теперь деструкторы по умолчанию равны noexcept
(то есть noexcept(true)
).
Теперь у меня есть библиотека, для которой я получаю много предупреждений компилятора из-за того, что деструктор некоторых классов может бросать, но он не помечен noexcept(false)
. Поэтому я решил изменить это и добавить спецификацию. Однако эти классы унаследованы от некоторого общего родителя Base
, поэтому это вынудило его добавить его также в деструктор родительского класса, иначе я получу ошибку компилятора overriding ‘virtual Base::~Base() noexcept
.
Конечно, я могу добавить noexcept(false)
также в базовый класс (на самом деле его достаточно добавить, насколько я понимаю), но есть много классов, которые наследуют от Base
, и все они наследуют атрибут noexcept(false)
(насколько я понимаю). Однако сам деструктор базового класса будет никогда не бросить, и только некоторые из производных классов могут реально бросить. Поэтому появляется отходы, чтобы отметить деструктор базового класса noexcept(false)
только для нескольких классов.
Итак, у меня есть два вопроса:
1) Есть ли способ обойти это? Я не могу удалить броски в нескольких производных классах, которые бросают, поскольку они важны.
2) Я не уверен, насколько можно оптимизировать оптимизацию компилятора из-за добавления noexcept(false)
в базовый класс (практически) всех классов в библиотеке. Когда (когда-либо) это меня касается?
Редактировать: на боковой ноте, есть способ изменить значение по умолчанию для noexcept
внутри проекта? Возможно, вариант компилятора?
Edit: так как там было много обратной связи, я должна правка, несколько замечаний:
1) Я не пишу библиотеку, и я, конечно, не планирую переписать деструкторы многих классов. Чтобы добавить noexcept(false)
к некоторым базовым классам, уже достаточно боли. И обращение к другой библиотеке не является вариантом (по разным причинам, выходящим за рамки программирования).
2) Когда я сказал: «Я не могу удалить броски в нескольких производных классах, которые бросают, поскольку они важны». Я имел в виду, что я считаю, что код должен заканчиваться в этом случае, поскольку что-то действительно плохое и неопределенное поведение может следовать в любом случае. По крайней мере, бросок приходит с небольшим объяснением того, что произошло.
3) Я понимаю, что бросать деструктор производного класса плохо, поскольку он может протекать из-за того, что деструктор родительского класса не вызван (это правильно?). Что было бы чистым путем, если нужно прекратить программу (чтобы избежать неясных ошибок позже) и все-таки позволить пользователю узнать, что произошло?
* «... Я не могу удалить« броски »в нескольких производных классах, которые бросают, так как они важны.» * - Похоже на плохой плохой и плохо плохо спроектированной библиотеки. [Throwing from Destructor] (http://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor?rq=1) является опасным. – WhiZTiM
Если возможно, попробуйте изменить деструкторы, чтобы они не бросали. Выбрасывание исключения из деструктора опасно, потому что деструкторы могут быть вызваны во время разматывания стека, когда другое исключение находится в полете (выброшено, но еще не поймано). Выброс исключения, когда другой находится в полете, прекратит выполнение программы. – Wyzard
"* Я не могу удалить броски в нескольких производных классах, которые бросают, поскольку они важны. *« Да, вы можете. Вы просто не хотите, чтобы изменения действительно делали это *. Но факт в том, что вы, несомненно, способны это сделать. Вы, возможно, разработали себя в угол, но вы всегда можете снова выстраиваться из него. –