Почему компилятор не жалуется на предложения catch? - PullRequest
4 голосов
/ 11 марта 2012

Этот код генерирует 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 ]

3 голосов
/ 11 марта 2012

Вопрос сформулирован немного странно, поэтому я предполагаю, что вы спрашиваете, почему

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 ++ принимает его без жалоб.

1 голос
/ 11 марта 2012

Оба исключения являются частными, и g ++, clang и EDG все жалуются на это.То есть, вероятно, ошибка в C ++ - использовать их, как вы, но ваш компилятор, похоже, ошибается в разрешении кода.Тем не менее, в разделе об обработке исключений на самом деле явно не говорится, что для перехватываемого исключения должен быть определенный доступ (в конце концов, закрытый класс будет доступен в члене «A»).Я предполагаю, что это привело к тому, что разработчики не проверяли этот доступ.

...