为啥 PRIVATE 成员函数不能成为另一个类的友元函数?

Posted

技术标签:

【中文标题】为啥 PRIVATE 成员函数不能成为另一个类的友元函数?【英文标题】: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”的私有成员

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

【问题讨论】:

Friend declaration in C++ - difference between public and private 的可能重复项 @hagubear 绝对不是那个副本。 您是在问为什么语言不允许这样做吗?在某些时候,有人认为(可以理解)这是一个坏主意。 因为否则它不会是私有的。 【参考方案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 成为朋友更具侵略性。

以上是关于为啥 PRIVATE 成员函数不能成为另一个类的友元函数?的主要内容,如果未能解决你的问题,请参考以下文章

关于c++的友元函数

Swift 中的友元类(访问内部类的私有成员)

c++,类的问题。private类型的是否只有类自己可以使用?与protect类型的有啥区别

C++ 友元

类与类之间的友元关系可以继承吗? 友元函数是类的成员函数吗?

友元相关