【问题标题】:Why the compiler doesn't complain about the catch clauses?为什么编译器不抱怨 catch 子句?
【发布时间】:2012-03-28 03:36:15
【问题描述】:

这段代码在VS2008中生成C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'

#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;
    }
}

当然,如果我在B 中公开ExceptionB{} 类,代码就会编译。

但我不明白为什么编译器不抱怨main() 中的两个catch 子句,因为A::ExceptionAA 中的私有类,而A::B::ExceptionBA::B 中的私有类.

【问题讨论】:

    标签: c++ visual-c++ try-catch nested-class private-members


    【解决方案1】:

    这个问题的措辞有点奇怪,所以我假设你在问为什么

    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++ 毫无怨言地接受了它。

    【讨论】:

    • 你是对的。如果我用catch( A::ExceptionA&amp; a) 替换catch( A::ExceptionA&amp; ),编译器会抱怨。您在标准中提到了第 15.6 章,但我找不到它,至少在标准最新草案 N3225 中。你能确认一下 15.6 第 1 段吗?
    • @user1042389:我在看 C++03。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-01
      • 2012-09-12
      • 2016-04-22
      • 1970-01-01
      • 2017-01-17
      • 2019-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多