Свой класс exception
Я создал свой класс MyException
class MyException: public std::exception
{
private:
std::string msg;
public:
MyException(std::string msg): std::exception(msg)
{
}
};
Пример взят из интернета, но у меня ругается компилятор (gcc) на строчку std::exception(msg)
note: candidate: 'constexpr std::exception::exception(const std::exception&)'
no matching function for call to 'std::exception::exception(std::__cxx11::string&)'
MyException(std::string msg): std::exception(msg){
no known conversion for argument 1 from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'const std::exception&'
После нашел другой пример
class MyException: public std::exception
{
private:
public:
MyException(std::string msg);
~MyException() = default;
const char* what() const noexcept override;
};
Тут все работает, но у меня есть пару вопросов:
- Почему я не могу реализовать первый пример, хотя у другого человека получилось? (c++11)
- Почему в строчке const char(указатель) what() const noexcept override; используется последовательность const noexcept override;? Почему я не могу написать просто noexcept override или просто override. Насколько я знаю noexcept не позволяет выбросить исключение. И почему используется два раза const? Мы же уже указали, что функция будет константная
Ответы (3 шт):
Наверное вы не внимательно смотрели, или там была опечатка, потому что конструктор std::exception не принимает в аргумент std::string, а принимает только С_строку(в некоторых реализациях). Поэтому нужно ему передать именно такую строку. Вот, например, так:
MyException(std::string msg) : std::exception(msg.c_str())...спецификатор
const noexcept overrideможет быть только для функции члена. Это значит, что функция член определена и для константных объектов (то есть она не изменяет состояние объекта), не генерирует исключение(помощь компилятору) и переопределен в производном классе(то есть это виртуальная функция_член).
А второй констант относится к возвращаемому типу(возвращает указатель на константную строку.
Дело в том, что по стандарту exception не имеет конструктора иного, кроме как по умолчанию.

Так что формально ваш код
MyException(std::string msg): std::exception(msg)
ошибочен. Другое дело, что некоторые компиляторы от стандарта отходят и допускают
exception::exception(const string&)
Так что по-хорошему, хранить сообщение должны вы сами. Или использовать в качестве родительского иной класс.
В соседнем ответе объяснили, в чем ошибка. А теперь как чинить.
Да, можно положить в свой класс std::string с текстом ошибки, и перегрузить what(), чтобы он его возвращал. Но есть нюанс: стандартные исключения можно копировать, гарантированно не получая исключений (например от нехватки памяти) - у них внутри какой-то аналог std::shared_ptr<std::string>.
А ваше исключение при копировании сможет выбросить исключение (если new кинет исключение) - маловероятно, но все равно не по фен-шую.
Чтобы этого не произошло, можно не хранить строку самому, а унаследоваться от std::runtime_error или std::logic_error, и хранить строку в нем. Или, если совсем не хочется наследоваться, хранить один из этих классов в своем.