保持公共嵌套类的一部分仅对嵌套类可见

时间:2011-01-13 12:26:23

标签: c++ friend nested-class friend-class

我在c ++中有一个嵌套类,必须是公共的。但我需要一些外部世界可见的方法,其余的只能 到嵌套类。那就是:

class set {
public:
    class iterator {
        innerMethod();
    public:
        outerMethod();
    }
}

我希望能够为set使用innerMethod()编写一个方法。如果我把它公之于众,我也可以从外面访问它,这是我绝对不想要的。有没有办法在不做“朋友类集”的情况下做到这一点?

提前致谢!

5 个答案:

答案 0 :(得分:2)

没有使用friend关键字,您可以做到这一点。

你在评论中说:

  

在我目前的编程课程中   据说,使用'朋友'是   不明智和普遍考虑   大多数情况下“糟糕的编程”   除非真的没有别的办法   周围。所以我试着避免它   尽可能多。

friend打破了封装,也许这就是为什么你的班级老师说这是错误的编程。 但是成员函数也破坏了封装,那你为什么要使用它们呢?为什么不避免它们呢? friend以与成员函数相同的方式打破封装; 因此,如果您在需要时使用成员函数时感觉很舒服,那么您应该在需要的时候使用friend以及会很舒服。因为某种原因,它们都存在于C ++中!

class set {
public:
 class iterator 
 {
  friend class set; //<---- this gives your class set to access to inner methods!

  void innerMethod(){}
 public:
  void outerMethod(){}
 };
 iterator it;

 void fun()
 {
  it.innerMethod();
  it.outerMethod();
 }
};

请参阅:How Non-Member Functions Improve Encapsulation

答案 1 :(得分:1)

不,我认为还有其他非hacky方法,但使用friend - 指令。

friend存在就是出于这种目的,你为什么要避免它呢?

答案 2 :(得分:1)

试着问:有没有办法添加2个数字而不添加它们? 对不起,如果我很苛刻,但朋友类就是这样......

答案 3 :(得分:1)

是的。

我一直试图提倡这个方法一段时间,基本的想法是使用Key类。

虽然这实际上并没有删除 friend的使用,但它确实减少了公开的实现细节集。

class set;

// 1. Define the Key class
class set_key: noncopyable { friend class set; set_key() {} ~set_key() {} };

class set
{

  // 2. Define the iterator
  class iterator
  {
  public:
    void public_method();

    void restricted_method(set_key&);

  }; // class iterator

}; // class set

现在,restricted_method是公开的,因此set不需要对iterator的任何特殊访问权限。但是,它的使用仅限于那些能够传递set_key实例的人......而且只有set才能构建这样的对象。

请注意,set实际上可能会将set_key对象传递给其信任的其他人。这是传统意义上的关键:如果你把公寓的钥匙交给某人,它可能会委托给另一个人。但是由于密钥类的语义(不可复制,只有set可以构造并销毁它),这通常仅限于key对象范围的持续时间。

请注意,恶意黑客总是可能的,即*((set_key*)0)。这个方案可以保护Murphy,而不是Machiavelli(无论如何都不可能在C ++中)。

答案 4 :(得分:0)

您可以这样做:

课程集

{

public:
    class iterator
    {
        protected:
            iterator(){};
            virtual ~iterator(){};

        public:
            //outer world methods...
    };

private:
    class privateIterator : public iterator
    {
        public:
            privateIterator(){};
            ~privateIterator(){}

        //inner methods;
    };

public:
    iterator* CreateIterator()
    {
        return new privateIterator();//this is used to be sure that you only create private iterator instances
    }

};

我不知道这是否是正确的答案,但现在它确实使用了朋友的关键工作,它隐藏了一些方法。唯一的问题是你不能声明privateIterator而且你总是必须使用CreateIterator来创建一个实例......