Почему компилятор не жалуется на предложения 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"). Я предполагаю, что это привело к тому, что разработчики не проверяли этот доступ.

Другие вопросы по тегам