This code generates C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'
in 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;
}
}
Of course, If I make the class ExceptionB{}
public in B
, the code compiles.
But I don't understand why the compiler does't complain about the 2 catch clauses in main()
, as A::ExceptionA
is a private class in A
and A::B::ExceptionB
is a private class in A::B
.
The question is worded a bit strangely, so I'm assuming that you're asking why
i % 2 ? throw ExceptionA() : throw A::B::ExceptionB();
does not compile, while
catch( A::ExceptionA& )
catch( A::B::ExceptionB& )
does.
If you take a look at a copy of your handy dandy C++ standard (Chapter 11, paragraph 4), it says the following:
It should be noted that it is access to members and base classes that is controlled, not their visibility. Names of members are still visible, and implicit conversions to base classes are still considered, when those members and base classes are inaccessible.
The difference then in the above is that in the first case, you are trying to call a member of A::ExceptionA
or A::B::ExceptionB
-- the constructors for the exception. But in the catch statement, you're not accessing a member of any of those; you're only accessing the type name.
That said, I still believe this is a bug in MSVC++. The standard also says, in chapter 15.6 paragraph 1:
If the exception-declaration in a catch clause has class type, and the function in which the catch clause occurs does not have access to the destructor of that class, the program is ill-formed.
which your sample seems to violate, yet MSVC++ is accepting it without complaint.