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

发布于 2024-10-12 06:33:17 字数 316 浏览 2 评论 0原文

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

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

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

提前致谢!

I have a nested class in c++ which has to be public. But I need some of its methods visible to the outer world, and the rest visible only to the nesting class. That is:

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

I want to be able to write a method for set which uses innerMethod(). If I make it public, I can access it from outside as well, which is something that I definitely don't want. Is there a way to do it without doing the "friend class set" thing?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

秋意浓 2024-10-19 06:33:17

如果不使用 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();
 }
};

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

There is NO GOOD WAY you can do this, without using friend keyword.

In the comment you said:

In the programming class I currently
take, using 'friend' was said to be
ill-advised and generally considered
"bad programming" for the most part,
unless there is really no other way
around it. So I try to avoid it as
much as possible.

friend breaks encapsulation, maybe that is the reason why your class teacher said it's bad-programming. But member-functions too break encapsulation, then why do you use them? Why not avoid them too? friend breaks encapsulation in the same way as do member-functions; so if you're comfortable using member-functions when they're needed, then you should be comfortable using friend also when they're needed. Both exist in C++ for a reason!

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

See this : How Non-Member Functions Improve Encapsulation

情丝乱 2024-10-19 06:33:17

不,我不认为除了使用 friend 指令之外还有其他非 hacky 方法。

friend 的存在正是为了这种目的,你为什么要避免它呢?

No, I don't think there are other non-hacky methods but using the friend-directive.

friend exists right for this kind of purpose, why would you avoid it?

独﹏钓一江月 2024-10-19 06:33:17

尝试问:有没有什么方法可以将两个数字相加而不相加?
抱歉,如果我很严厉,但朋友等级正是为了这个......

Try asking: is there any way to add 2 numbers without adding them?
Sorry if I'm harsh, but friend class is for exactly that...

好多鱼好多余 2024-10-19 06:33:17

是的,有。

我已经尝试提倡该方法有一段时间了,基本思想是使用 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++ 中是不可能的)。

Yes there is.

I've been trying to advocate the method for a while now, the basic idea is to use a Key class.

While this does not actually remove the use of friend, it does reduce the set of exposed implementations details.

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

Now, restricted_method is public, so set does not need any special access to iterator. However the use of it is restricted to those able to pass a set_key instance... and conveniently only set may build such an object.

Note that set may actually pass a set_key object to someone else it trusts. It is a key in the traditional sense: if you give a key of your flat to someone, it may entrust it to another person. However because of the semantics of the key class (non copyable, only set may construct and destroy it) this is normally limited to the duration of the scope of the key object.

Note that a evil hack is always possible, namely *((set_key*)0). This scheme protects from Murphy, not Machiavelli (it's impossible in C++ anyway).

水中月 2024-10-19 06:33:17

你可以这样做:

class set

{

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 来创建一个实例......

You can do something like this:

class set

{

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
    }

};

I don't know if it's the right answer, but it does now uses friend key work and it hides some of the methods. The only problem is that you can't declare privateIterator and you always must use CreateIterator to create an instance...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文