Краткий ответ: вы захотите выбросить исключения как объекты, а не как указатели. Вы будете ловить их как ссылки.
Более длинный ответ: все перечисленные варианты действительны. В общем, причина, по которой вы захотите бросить объект, а не указатель, заключается в том, что вы делаете выбор для себя и своих клиентов при обнаружении исключения.
Если вы поймаете по указателю, catch (my_exception* e)
, то, глядя на него, вы не знаете, следует ли вам удалить память или нет.
Если вы ловите по значению, catch (my_exception e)
, тогда у вас есть риск нарезки, если объект исключения оказывается базовым классом с некоторыми другими производными классами.
Отлов по ссылке не имеет ни одной из этих проблем. Если вы напишите catch (my_exception& r)
, тогда вы сможете ловить полиморфные объекты, и вам не придется беспокоиться об освобождении памяти.
Итак, чтобы ответить на другой вопрос, когда вы бросаете, просто бросьте временный объект: throw my_exception()
. Это создает временный объект, который (вероятно) копируется при броске, перехватывается по ссылке и автоматически уничтожается, когда он выходит из области видимости в конце вашего блока catch. (На самом деле это еще одно преимущество функции «поймать по ссылке» по сравнению с «поймай по значению», так как «поймай по значению» создает еще одну копию при ее обнаружении.)
Что касается других ваших производных классов исключений, то это выбор стиля. Вывод из my_exception с другой реализацией what () довольно стандартен. Я бы не сказал, что вам нужно увлекаться хранением строк или экземпляров в статических объектах - они маленькие, и их создание займет практически не время по сравнению с процессом разматывания стека при возникновении исключения.