3

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

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

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

提前致谢!

4

5 回答 5

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

请参阅:非成员函数如何改进封装

于 2011-01-13T12:34:27.850 回答
1

试试问:有没有什么办法可以不加两个数字就加起来?对不起,如果我很苛刻,但朋友班正是为了这个......

于 2011-01-13T12:33:06.153 回答
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). 这个方案可以保护墨菲,而不是马基雅维利(无论如何在 C++ 中是不可能的)。

于 2011-01-13T14:24:08.620 回答
1

不,我认为除了使用 -directive 之外,没有其他非 hacky 方法friend

friend为这种目的而存在,你为什么要避免它?

于 2011-01-13T12:28:05.467 回答
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 来创建一个实例......

于 2011-01-13T12:51:01.267 回答