Не удается поймать класс, полученный из std :: exception, по ссылке на std :: exception - PullRequest
0 голосов
/ 02 мая 2018

Я создал собственный класс исключений, который наследуется от std :: exception.

#include <iostream>

class Exception : std::exception {
public:
    const char* what() const noexcept override {
        return "test";
    }
};

int main() {
    try {
        throw Exception();
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
    }
}   

Эта программа, скомпилированная g ++ -stdc ++ = 17 в Ubuntu, приводит к тому, что исключение не перехватывается блоком catch, даже если предполагается, что перехват по ссылке также перехватывает производные исключения. Он вызывает std :: terminate, даже если это происходит в блоке try, который перехватывает свой базовый класс по ссылке. То же самое происходит, если Exception наследуется от std :: runtime_error и передает «тест» конструктору std :: runtime_error в своем собственном конструкторе. Обычно решение состоит в том, чтобы перехватывать только с использованием Exception, но в моем исходном коде мне нужно отлавливать различные типы исключений, которые все наследуются от std :: exception. Почему это происходит? Не работает ли отлов по ссылке на базу? Как я могу перехватить все исключения, происходящие из std :: exception, используя один блок catch?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Когда вы наследуете от базового класса во время определения class, модификатор доступа по умолчанию для наследования - private. Это означает, что два следующих определения эквивалентны:

class derived : base { /* ... */ };
class derived : private base { /* ... */ };

Язык не позволяет 1 ссылаться на производный класс из частной базы 2 . Например, следующий код не компилируется:

int main()
{
    derived d;
    base& b = d; // <== compilation error
}
error: 'base' is an inaccessible base of 'derived'
     base& b = d;
               ^

живой пример на wandbox.org


По этой причине ваш блок catch не может обработать Exception. Измените свое наследство на public ...

class Exception : public std::exception

... и ваш оригинальный код будет работать.

живой пример на wandbox.org


1 См. [dcl.init.ref] и [conv.ptr] .

2 Если только вы не находитесь в области действия derived. Смотрите живой пример на wandbox.org .

0 голосов
/ 02 мая 2018

Вам необходимо публично получить от std::exception

class Exception : public std::exception

Тогда ваш вывод равен

test

Подробнее об этой теме см. Разница между частным, общедоступным и защищенным наследованием .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...