2012-03-11 101 views
4

此代码在VS2008中生成C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'为什么编译器不会抱怨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,代码编译。

但我不明白为什么编译器简化版,在main()抱怨的2个catch子句,为A::ExceptionAA的私有类和A::B::ExceptionBA::B私有类。

回答

3

问题的措辞有些奇怪,所以我假设你问为什么

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

不能编译,而

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

一样。

如果你看看你方便的花花公子C++标准(第11章,第4段)的副本,它说以下内容:

应当指出的是,访问成员和基类这是受控的,而不是他们的知名度。 成员的名称仍然可见,并且当这些成员和基类不可访问时,仍然会考虑隐式转换为基类。

再在上面不同的是,在第一种情况下,你想调用A::ExceptionAA::B::ExceptionB成员 - 为异常的构造函数。但在catch语句中,您没有访问任何一个成员;你只能访问类型名称。


这就是说,我仍然认为这是MSVC++中的一个错误。该标准还说,在第15.6段第1段中提到:

如果catch子句中的异常声明具有类类型,并且发生catch子句的函数无法访问该类的析构函数,该计划是不健全的。

您的示例似乎违反了,但MSVC++没有投诉就接受它。

+0

你说得对。如果我用'catch(A :: ExceptionA&a)'替换'catch(A :: ExceptionA&)',编译器会抱怨。您在标准中提到了第15.6章,但我找不到它,至少在标准最新草案N3225中找不到。你能确认15.6段落1吗? – Belloc 2012-03-11 15:27:38

+0

@ user1042389:我在这里查看C++ 03。 – 2012-03-11 15:31:01

+0

谢谢。我给你的答案的功劳。 – Belloc 2012-03-11 15:33:10

1

这两个例外都是私有的,g ++,clang和EDG都抱怨它。也就是说,像你一样使用它们可能是C++中的一个错误,但是你的编译器似乎在允许代码时是错误的。但是,有关异常处理的部分实际上并未明确指出被捕获的异常需要具有特定的访问权限(毕竟,私有类可以在'A'的成员中访问)。我想这导致开发人员不检查此访问权限。

相关问题