Вопрос сформулирован немного странно, поэтому я предполагаю, что вы спрашиваете, почему
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 ++ принимает его без жалоб.