朋友应该在嵌套类中传递吗?

时间:2011-06-21 02:50:52

标签: c++ friend standards-compliance

class private_object
{
private:
  struct make_public;
  friend struct make_public;
  static void method1() {}
};

struct private_object::make_public
{
  class nested_outer
  {
    void callFromOuter() 
    { private_object::method1(); }   // Should this be an error?

    class nested_inner
    {
      void callFromInner() 
      { private_object::method1(); } // How about this one?
    };
  };
};
当我试图将一个开源项目移植到borland下编译时,这个友谊问题出现了。根据{{​​3}}和两个半相关问题parashifthere,上述示例不应有效。

然而,在七个不同的编译器 1 上测试后,只有borland和dmc抱怨。这种行为让我感到惊讶,因为我并不认为友谊会在嵌套类中传递。

所以这提出了几个问题:

  • 什么是正确的行为?我猜它是大多数编译器都接受的那个。
  • 如果这是正确的行为,为什么友谊传递的实例好吗?
  • 如果这是正确的,那么这也意味着标准的变化。在标准中允许这样做的原因是什么?
  • 对于拒绝此代码的编译器,什么是适当的解决方法?请记住,实际项目可能包含相当深的嵌套,因此我正在寻找一种半可扩展的解决方案。

<子> 1。测试了mingw-gcc 4.5.2,clang,borland c ++ builder2007,数字火星,开放式watcom,visualc2010和comeau online

2 个答案:

答案 0 :(得分:3)

在C ++ 03中,嵌套类默认情况下不能访问封闭类的privateprotected成员(参见§11.8/ 1)。但如果你让他们成为封闭类的朋友,那么他们就可以访问它们。但是嵌套类的嵌套类仍然不是最外层封闭类的朋友,嵌套类的嵌套类不能访问最外层封闭类的私有和受保护成员;如前所述,它甚至无法访问直接封闭类的私有和受保护成员。你正在做的是,因此这是不允许的。

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

它是C ++ 03标准中的缺陷。

顺便说一句,它是C ++ 03标准中的缺陷。由于嵌套类是成员,因此它应该可以访问私有成员和受保护成员,就像任何其他成员一样:

§9.2/ 1(C ++ 03):

  

类的成员是数据成员,成员函数(9.3),嵌套类型 ...嵌套类型是类(9.1,9.7)和类中定义的枚举(7.2)...

请参阅缺陷报告

答案 1 :(得分:1)

我不知何故觉得这应该是允许。虽然我不确定标准行为。有人可以指出。

  

对于拒绝此代码的编译器,   什么是合适的   解决办法:

我能想到的最好是做一个包装器:

struct private_object::make_public
{
  static void wrap_method1() { private_object::method1(); }
  // use wrap_method1() everywhere else
  // ...
};