Исключения C++ и Наследование от станд.:: исключение

Учитывая этот пример кода:

#include <iostream>
#include <stdexcept>

class my_exception_t : std::exception
{
public:
    explicit my_exception_t()
    { }

    virtual const char* what() const throw()
    { return "Hello, world!"; }
};

int main()
{
    try
        { throw my_exception_t(); }
    catch (const std::exception& error)
        { std::cerr << "Exception: " << error.what() << std::endl; }
    catch (...)
        { std::cerr << "Exception: unknown" << std::endl; }

    return 0;
}

Я получаю следующий вывод:

Exception: unknown

Все же просто делая наследование my_exception_t от std::exception public, Я получаю следующий вывод:

Exception: Hello, world!

Кто-то мог объяснить мне, почему тип наследования имеет значение в этом случае? Бонусные очки для ссылки в стандарте.

12
задан Deduplicator 3 July 2015 в 16:56
поделиться

2 ответа

Когда вы наследуете частным образом, вы не можете преобразовать или иным образом получить доступ к базовому классу вне класса. Поскольку вы просили что-то из стандарта:

§11.2/4:
Считается, что базовый класс доступен, если доступен придуманный открытый член базового класса. Если базовый класс доступен, то можно неявно преобразовать указатель на производный класс в указатель на этот базовый класс (4.10, 4.11).

Проще говоря, для чего-либо за пределами класса это все равно, что вы никогда не наследовались от std::exception, потому что он приватный. Следовательно, оно не сможет быть поймано в std::exception&, поскольку преобразования не существует.

21
ответ дан 2 December 2019 в 04:53
поделиться

Может ли кто-нибудь объяснить мне, почему тип наследования имеет значение в в этом случае? Бонусные очки за ссылку в стандарте.

Тип наследования не имеет значения. Имеет значение только то, что у вас есть доступное преобразование к одному из типов catch. Так получилось, что поскольку это не публичное наследование, то нет публичного доступного преобразования.


Объяснение:

Вы можете увидеть такое же поведение здесь:

class B
{
};

class C1 : B
{
};

class C2 : public B
{
};

int main(int argc, char** argv)
{
    B& b1 = C1();//Compiling error due to conversion exists but is inaccessible
    B& b2 = C2();//OK
    return 0;
}

Брошенное исключение перехватывается блоком catch только если:

  1. Блок catch имеет соответствующий тип, или
  2. Блок catch предназначен для типа, который имеет доступное преобразование
  3. Блок catch является catch(...)
10
ответ дан 2 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: