【问题标题】:Why can't a PRIVATE member function be a friend function of another class?为什么 PRIVATE 成员函数不能成为另一个类的友元函数?
【发布时间】:2015-01-13 09:21:45
【问题描述】:
class x
{
    void xx() {}
};

class y
{
    friend void x::xx();
};

这会导致类似

的错误

错误:友元函数“xx”是“x”的私有成员

为什么我不能将私有成员函数声明为另一个类的友元?

【问题讨论】:

标签: c++ class language-lawyer friend access-rights


【解决方案1】:

[class.friend]/9:

朋友声明指定的名称应可在 包含朋友声明的类的范围。

原因很简单; private会员必须遵守明确的规则:

一个类的成员可以是

  • private;也就是说,它的名称只能被声明它的类的成员和朋友使用。

允许在不相关类的声明中命名私有成员将违反此规则:它允许另一个类依赖于实现细节而无需明确允许。例如,当更改私有成员的名称、类型或签名,或完全删除它时,这会成为问题;这是为了不破坏该类的接口。

这可以通过将整个x 设为y 的朋友来规避:

class x {
    void xx() {}
};

class y {
    friend x;
};

Demo.

【讨论】:

  • 可能我没看懂问题,但不应该是相反的方式,就是让y成为x的朋友吗?在您的示例中,y 将无法访问 x 的私有方法。
  • @IvanSmirnov 最初的 sn-p 的意图是允许x 的成员访问y 的私​​人数据。
  • 啊,对,不是最直观的东西。谢谢,知道了。
  • @IvanSmirnov 您建议的是 hvd 下面的方法,这似乎是不必要的复杂。
【解决方案2】:

制作x::xxprivate的想法应该是x::xx是其他类不应该依赖的实现细节。这不仅仅意味着 x::xx 不能被其他类调用,它意味着,或者更确切地说,它应该意味着,例如将 x::xx 重命名为 x::xy 不应该破坏班级本身和班级朋友以外的任何内容。

在您的情况下,将 x::xx 重命名为 x::xy 会导致类 y 出现错误,即使它不是 x 的朋友。

避免这种情况的一种方法是让y 成为x 的朋友,以便y 可以访问xprivate 成员。然后它可以将x::xx 声明为friend

(注意:对于“为什么编译器不允许这个?”这个问题更直接的回答是“因为标准不允许这个。”,这自然会引出后续问题“为什么标准不允许这个。”允许这个吗?”。我正在尝试回答这个后续问题。)

【讨论】:

  • 我可以拥有一个私有的虚拟成员函数,并在子类中被覆盖。在基类中重命名该虚函数会破坏某些东西,不是吗?`
  • 我喜欢你所回答的问题究竟的区别。
  • @Columbo 你是对的。这是“它意味着”和“它应该意味着”之间的区别之一。 :)
  • 顺便说一句。你解决这个问题的方法很奇怪。让整个班级y 成为x 的朋友,以便能够与x 的成员成为朋友?为什么要绕道?
  • @Columbo 这取决于具体情况。通常,当然,只需将所有 x 设为 y 的朋友即可。这是显而易见的解决方案。但是,如果 x 是一个有很多功能的大类,而 y 是一个小助手类,那么让 yx::xx 成为朋友远比让所有 x 成为朋友更具侵略性。
猜你喜欢
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 2011-05-20
相关资源
最近更新 更多