嵌套的C ++类外部成员的访问权限

时间:2011-02-17 16:13:26

标签: c++

此代码不起作用(MS VS 2005),

b->funcA();
B::iterator iter;

无法访问A类声明的受保护成员。

如果我删除D类,一切都很好地编译。

我想知道这只是一个错误还是标准?

class A
{
protected:
    void funcA() {  }
    class iterator {    };
};

class D {
    class B : public A {
        class C {
            B* b;
        public:
            void funcC() {
                b->funcA();
                B::iterator iter;
            }
        };
    public:
        void funcB() {
            funcA();
        }
    };
};

谢谢!

3 个答案:

答案 0 :(得分:3)

当前的C ++标准(C ++ 03)具有以下限制,会使您的代码格式错误:

  

嵌套类的成员对封闭类的成员没有特殊访问权限,也没有对已经为封闭类授予友谊的类或函数;应遵守通常的准入规则(C ++ 03 11.8 / 1)。

但是,这条规则在即将推出的C ++标准(C ++ 0x)中已被颠倒过来。该段落现为:

  

嵌套类是成员,因此具有与任何其他成员相同的访问权限。封闭类的成员对嵌套类的成员没有特殊访问权限;应遵守通常的访问规则(C ++ 0x Draft N3225 11.8 / 1)。

所以,根据旧的解释,你的代码是不正确的,但在新的解释下,它是正确的。这基本上是原始C ++标准中的一个缺陷;该缺陷于1998年被注意到,并且在2001年同意更正。您可以在CWG Defect 45中找到相关详细信息。


请注意,无论您想使用哪种解释,我认为编译器中仍然存在错误。以下是最小repro,并在使用Visual C ++ 2010时生成相同的错误:

class A {
protected:
    void f() { }
};

struct D {
    struct B : A {
        struct C {
            void g() { 
                B().f(); 
            }
        };
    };
};

但是,如果删除D并将B放在全局命名空间中,编译器将接受该代码。

答案 1 :(得分:0)

C嵌套在B中的事实并没有给B的成员提供C特殊访问权限。

funcA()的解决方案: (1)使funcA()公开。 或(2)改为调用funcB()(委托给funcA())。

迭代器解决方案:将迭代器设为公共。

答案 2 :(得分:0)

CB的嵌套类。嵌套类无法访问封闭类的私有成员和受保护成员。这就是为什么代码不能编译,并正确地给出编译错误。

C ++标准版(2003)以11.8美元/ 1 [class.access.nest]的形式说,

  

嵌套类的成员没有   特殊访问成员   封闭类,也不包括类或   授予友谊的功能   到一个封闭的班级;通常   准入规则(第11条)应为   服从。一个封闭的成员   class没有特殊的访问权限   嵌套类的成员;通常   准入规则(第11条)应为   服从。

标准本身的例子:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // error: E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // error: I::y is private
   }
};

因此,根据它,D的存在或不存在不会影响任何事情。它应该给出编译错误,即使D不存在。

昨天创建了类似主题:Are inner classes in C++ automatically friends?


顺便说一句,它是C ++ 03中的一个缺陷,已在C ++ 0x中得到纠正。

这在C ++ 0x中是允许的。见Access to nested classes