Почему компилятор не жалуется на предложения catch?
Этот код генерирует C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'
в VS2008.
#include <iostream>
class A
{
class ExceptionA{};
class B
{
class ExceptionB{};
public:
B();
};
public:
A(int);
};
A::B::B()
{
throw ExceptionB();
}
A::A(int i)
{
i % 2 ? throw ExceptionA() : throw A::B::ExceptionB(); // C2248 !!
}
int main()
{
try
{
A a(3);
}
catch( A::ExceptionA& )
{
std::cout << "A::ExceptionA" << std::endl;
}
catch( A::B::ExceptionB& )
{
std::cout << "A::B::ExceptionB" << std::endl;
}
}
Конечно, если я сделаю урок ExceptionB{}
публика в B
код компилируется.
Но я не понимаю, почему компилятор не жалуется на 2 предложения catch в main()
, как A::ExceptionA
это частный класс в A
а также A::B::ExceptionB
это частный класс в A::B
,
2 ответа
Вопрос сформулирован немного странно, поэтому я предполагаю, что вы спрашиваете, почему
i % 2 ? throw ExceptionA() : throw A::B::ExceptionB();
не компилируется, пока
catch( A::ExceptionA& )
catch( A::B::ExceptionB& )
делает.
Если вы взглянете на копию вашего удобного стандарта C++ денди (глава 11, пункт 4), он скажет следующее:
Следует отметить, что контролируется доступ к членам и базовым классам, а не их видимость. Имена членов все еще видны, и неявные преобразования в базовые классы все еще рассматриваются, когда эти члены и базовые классы недоступны.
Разница в приведенном выше заключается в том, что в первом случае вы пытаетесь вызвать члена A::ExceptionA
или же A::B::ExceptionB
- конструкторы для исключения. Но в операторе catch вы не получаете доступа ни к одному из них; вы только получаете доступ к имени типа.
Тем не менее, я все еще считаю, что это ошибка в MSVC++. Стандарт также гласит в главе 15.6 параграф 1:
Если объявление исключения в предложении catch имеет тип класса, а функция, в которой встречается предложение catch, не имеет доступа к деструктору этого класса, программа некорректна.
что ваш образец, кажется, нарушает, но MSVC++ принимает его без жалоб.
Оба исключения являются частными, и g++, clang и EDG все жалуются на это. То есть, вероятно, ошибка в C++ при их использовании, как и у вас, но ваш компилятор, похоже, ошибается в разрешении кода. Тем не менее, в разделе об обработке исключений на самом деле явно не говорится, что для отслеживаемого исключения должен быть определенный доступ (в конце концов, закрытый класс был бы доступен в члене "A"). Я предполагаю, что это привело к тому, что разработчики не проверяли этот доступ.