开发者

Nested C++ class outer members' access

This code does not work (MS VS 2005),

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

cant access protected members declared in class A.

If I remove class D, everything compiles nicely.

I wonder if it's just a bug or standard?

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();
        }
    };
开发者_开发知识库};

Thanks!


The current C++ standard (C++03) has the following restriction that would make your code ill-formed:

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules shall be obeyed (C++03 11.8/1).

However, this rule has been reversed in the forthcoming C++ standard (C++0x). The paragraph now reads:

A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules shall be obeyed (C++0x Draft N3225 11.8/1).

So, under the old interpretation, your code is incorrect but under the new interpretation it is correct. This is basically a defect in the original C++ Standard; the defect was noted in 1998 and the correction was agreed to in 2001. You can find details on that in CWG Defect 45.


Note that regardless which interpretation you want to use, I think there is still a bug in the compiler. The following is the minimal repro, and generates the same error when using Visual C++ 2010:

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

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

However, if you remove D and put B in the global namespace, the compiler accepts the code.


The fact that C is nested in B doesn't give C special access to B's members.

Solutions for funcA(): (1) Make funcA() public. or (2) Call funcB() instead (delegating to funcA()).

Solution for iterator: Make iterator public.


C is nested class of B. Nested class cannot access private and protected members of enclosing class. That is why the code doesn't compile, and correctly gives compilation error.

The C++ Standard (2003) says in $11.8/1 [class.access.nest],

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. The members of an enclosing class have no special access to members of a nested class; the usual access rules (clause 11) shall be obeyed.

Example from the Standard itself:

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

So according to it, presence or absence of D should not effect anything. It should give compilation error, even if D is absent.

Similar topic was created yesterday: Are inner classes in C++ automatically friends?


By the way, it's a defect in C++03 which has been corrected in C++0x.

This is allowed in C++0x. See this Access to nested classes

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜