2012-03-11 6 views
4

Этот код генерирует C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B' в VS2008.Почему компилятор не жалуется на предложения catch?

#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, код компилируется.

Но я не понимаю, почему компилятор does't жалуются на 2 улове статей в main(), так как A::ExceptionA частный класс в A и A::B::ExceptionB частный класс в A::B.

ответ

3

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

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:

Если исключение декларирование в пункте улова имеет тип класса, и функцию, в которой положение улова происходит, не имеет доступа к деструктор этого класса, программа плохо сформирована.

который ваш образец, кажется, нарушает, но MSVC++ принимает его без жалобы.

+0

Вы правы. Если я заменил 'catch (A :: ExceptionA &)' на 'catch (A :: ExceptionA & a)' компилятор жалуется. Вы упомянули главу 15.6 в Стандарте, но я не могу ее найти, по крайней мере, в проекте «Стандарт-последний» N3225. Не могли бы вы подтвердить пункт 15.6 пункта 1? – Belloc

+0

@ user1042389: Я смотрю на C++ 03 здесь. –

+0

Спасибо. Я даю вам кредит на ответ. – Belloc

1

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

Смежные вопросы