2012-03-11 4 views
4

이 코드는 VS2008에 C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'을 생성합니다. 내가 B에서 클래스 ExceptionB{} 대중을하면 물론컴파일러가 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; 
    } 
} 

은, 코드 컴파일합니다.

그러나 A::ExceptionAA에서 개인 클래스이고 A::B::ExceptionBA::B에서 개인 클래스로 컴파일러, main()에서 2 개 캐치 조항에 대해 불평 does't 왜 이해가 안 돼요.

답변

3

문제는 조금 이상하게 말로, 그래서

catch(A::ExceptionA&) 
catch(A::B::ExceptionB&) 

가하는 동안 나는,

i % 2 ? throw ExceptionA() : throw A::B::ExceptionB(); 

가 컴파일되지 않습니다 왜 요구하는지 있으리라 믿고있어.

회원들과 기본 클래스에 액세스 할 수 있음을 주목해야한다 : 당신이 당신의 편리한 멋쟁이 C++ 표준 (제 11 조 제 4 항)의 사본을 살펴 경우

, 그것은 다음과 같은 말한다 통제 된 것이지 가시성이 아니다. 구성원 이름은 계속 표시되며 기본 클래스에 대한 암시 적 변환은 구성원 및 기본 클래스에 액세스 할 수없는 경우에도 계속 고려됩니다. 예외의 생성자 -

다음 위의 차이는 첫 번째 경우에, 당신은 A::ExceptionA 또는 A::B::ExceptionB의 멤버를 호출하려고하는 것입니다. 그러나 catch 문에서 이들 중 하나의 멤버에 액세스하지는 않습니다. 당신은 단지 타입 이름에 접근하고 있습니다.


그렇다고해도 나는 이것이 MSVC++의 버그라고 생각한다. 표준은 또한 장 15.6 단락 1에서 말합니다 :

catch 절의 예외 선언에 클래스 유형이 있고 catch 절이 발생하는 함수가 해당 클래스의 소멸자에 액세스하지 못하는 경우, 프로그램이 잘못 형성되었습니다.

샘플이 위반하는 것으로 보이지만 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++에서 오류를 사용하는 것처럼 오류가 발생하지만 컴파일러에서 코드를 허용하는 것은 잘못된 것으로 보입니다. 그러나 예외 처리 섹션에서는 실제로 catch 된 예외가 특정 액세스 권한을 가져야한다고 명시하지는 않습니다 (결국 'A'멤버에서 개인 클래스에 액세스 할 수 있음). 나는 이것이 개발자들로 하여금이 접근을 점검하지 못하게 만들었다 고 생각한다.