Q1: да. Вы можете выбросить любой тип, необязательные типы, которые наследуются от std :: exception.
Вы можете написать throw 1;
throw и int или throw "hello";
throw char*
, оба из которых не наследуются от std::exception
. однако это считается плохой практикой, потому что пользователь класса не может ожидать, что вы бросите что-нибудь. Если вы не хотите наследовать от std::exception
, обычно вы создаете собственную иерархию исключений.
Q2: перехват исключения по значению (2-й вариант) является плохой практикой, поскольку вы принудительно копируете экземпляр исключения и при этом возможно выполняете выделения, которые могут вызвать дальнейшие исключения.
Использование первой опции предполагает, что вы намереваетесь изменить e
в блоке catch, чего также вам, вероятно, хотелось бы избежать, поскольку исключения обычно остаются неизменными после создания. Единственное, что осталось, это третий вариант.