Исключения и наследование С++ из std:: exception
Учитывая этот пример кода:
#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!
Не мог бы кто-нибудь объяснить мне, почему в этом случае имеет значение тип наследования? Бонусные баллы для справки в стандарте.
Ответы
Ответ 1
Когда вы наследуете конфиденциально, вы не можете конвертировать или иным образом обращаться к этому базовому классу за пределами класса. Поскольку вы просили что-то из стандарта:
§11.2/4:
Говорят, что базовый класс доступен, если доступный публичный член базового класса доступен. Если базовый класс доступен, можно неявно преобразовать указатель на производный класс в указатель на этот базовый класс (4.10, 4.11).
Проще говоря, для чего-либо вне класса это похоже на то, что вы никогда не унаследовали от std::exception
, потому что он закрыт. Ergo, он не сможет попасть в предложение std::exception&
, поскольку никакого преобразования не существует.
Ответ 2
Может кто-нибудь, пожалуйста, объясните мне, почему тип наследования имеет значение в Это дело? Бонусные баллы за ссылка в стандарте.
Тип наследования не имеет значения. Важно только то, что у вас есть доступное преобразование, доступное для одного из типов 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 имеет соответствующий тип или
- Блок catch предназначен для типа доступного преобразования
- Блок catch - это catch (...)