嵌套类:从嵌套的受保护类中访问封闭类的受保护成员

16

这段代码可以在MSVC/G++上编译:

class A{
protected:
    int i;
    class B{
    public:
        A* a;
        B(A* a_)
        :a(a_){
        }
        void doSomething(){
            if (a)
                a->i = 0;//<---- this part
        }       
    };
public:
    A()
    :i(0){
    }
};

正如您所看到的,虽然它没有被声明为友元,但B可以访问封闭类的“protected”部分。

这是标准(符合标准)的行为吗?

我有时使用这个特性,但我不记得有规定说嵌套的受保护类应自动获得对封闭类的所有受保护数据的访问权限。


重复问题。我现在不打算搜索原始内容。 :) - Johannes Schaub - litb
4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
17
在C++03标准中,11.8p1规定: “嵌套类的成员无法特殊访问封装类的成员。” 然而,对于标准的缺陷报告45的解决方案却相反,因此定义了您所看到的行为: “嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。” 在C++0x中,11.8的文本已更改以反映这一事实,因此这是符合C++03和C++0x的编译器的有效行为。 另请参见cprogramming.com论坛上的此线程

2
+1 很好的回答。然而,如果你在谷歌上搜索,会发现IBM XL编译器文档只提到了你所说的第一部分,并暗示OP的代码无法编译。因此,在C++0x被广泛实现之前,目前可移植的做法是在封闭类中声明嵌套类为友元。 - Praetorian
不错的发现。为了完整起见,最好提供一个链接。 :) - Håvard S
我之前有点懒 :-),这是链接。http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/language_ref/cplr061.html - Praetorian
@Praetorian 我倾向于将嵌套类声明为友元,因为这更好地描述了我希望代码如何运行,所以我也给了你的评论+1。 - Chris Huang-Leaver

5

我手头没有C++03的副本,但是有一份C++0x的草案(n3090):

11.8 嵌套类

1 嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。封闭类的成员对嵌套类的成员没有特殊访问权;应遵守通常的访问规则(第11条款)。

[ 示例:

class E {
    int x;
    class B { };
    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };
    int g(I* p) {
        return p->y; // error: I::y is private
    }
};
至少在下一个标准中,封闭类可以像任何普通成员函数一样访问外部类的成员。 更新: 目前的标准不允许这样做。但是已经提交了缺陷报告(DR 45)来修复这个问题。 更新#2: 我已经尝试使用VS2010、g++ (4.0.1 Apple)和Comeau (4.3.10.1)在严格的C++03模式下禁用了C++0x扩展,它们似乎都接受内部类成员访问外部类的私有成员。

0
这是标准(standard-conforming)行为吗? 不是。 根据 C++-2003 的规定: 第11.8.1节 嵌套类 嵌套类的成员没有特殊访问权,不能访问封闭类的成员,也不能访问向封闭类授权友元的类或函数;必须遵守通常的访问规则(第11条)。封闭类的成员没有特殊访问权,不能访问嵌套类的成员;必须遵守通常的访问规则(第11条)。
[Example:
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
    }
};
—end example]

但是在ISO/IEC N 3092的这个部分中有一个轻微的修改,其中提到:

嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。外围类的成员对嵌套类的成员没有特殊的访问权限;应遵守通常的访问规则(第11条)。


0

参考 $9.7/1。

“嵌套类在其封闭类的作用域内。除非使用显式指针、引用和对象名称,否则嵌套类中的声明只能使用封闭类中的类型名称、静态成员和枚举器。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,