C++ 为什么可以';私有成员函数不是另一个类的友元函数吗?

C++ 为什么可以';私有成员函数不是另一个类的友元函数吗?,c++,class,language-lawyer,friend,access-rights,C++,Class,Language Lawyer,Friend,Access Rights,这会导致如下错误: 错误:友元函数“xx”是“x”的私有成员 为什么我不能将私有成员函数声明为另一个类的朋友 朋友声明中指定的姓名应可在 包含友元声明的类的作用域 原因很简单,私人成员应遵守明确的规则: 类的成员可以是 私人;也就是说,它的名称只能由声明它的类的成员和朋友使用 允许在无关类内的声明中命名私有成员将违反此规则:它允许另一个类依赖于实现细节而不被明确允许。例如,当更改私人成员的名称、类型或签名,或将其完全删除时,这会产生问题;这是为了不破坏该类的接口 这可以通过使整个x成为y的朋

这会导致如下错误:

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

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

朋友声明中指定的姓名应可在 包含友元声明的类的作用域

原因很简单,<代码>私人成员应遵守明确的规则:

类的成员可以是

  • 私人
    ;也就是说,它的名称只能由声明它的类的成员和朋友使用
允许在无关类内的声明中命名私有成员将违反此规则:它允许另一个类依赖于实现细节而不被明确允许。例如,当更改私人成员的名称、类型或签名,或将其完全删除时,这会产生问题;这是为了不破坏该类的接口

这可以通过使整个
x
成为
y
的朋友来避免:

class x
{
    void xx() {}
};

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

.

使
x::xx
私有化的想法应该是
x::xx
是其他类不应该依赖的实现细节。这不仅仅意味着其他类不能调用
x::xx
,它还意味着,或者更确切地说,它应该意味着,例如将
x::xx
重命名为
x::xy
不应该破坏类本身和类的朋友之外的任何东西

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

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


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

可能重复的@hagubear肯定不是重复的。你是在问为什么语言不允许这样做吗?在某种程度上,有人认为(可以理解)这是个坏主意。因为否则它就不是私有的。我可以拥有一个私有的虚拟成员函数,并在子类中重写。在基类中重命名那个虚拟函数会破坏一些东西,不是吗?`我喜欢你回答什么问题的区别。@Columbo你是对的。这就是“它意味着”和“它应该意味着”之间的区别之一:)顺便说一句,你解决这个问题的方法很奇怪。让整个班级
y
成为
x
的朋友,以便能够成为
x
成员的朋友?为什么要绕道?@Columbo这取决于具体情况。通常,当然,只要让所有的
x
成为
y
的朋友即可。这是显而易见的解决办法。但是如果
x
是一个具有很多功能的大类,而
y
是一个很小的助手类,那么交
y
x::xx
朋友远比交所有
x
朋友要少。也许我不理解这个问题,但不应该是相反的,也就是说,让
y
成为
x
的朋友?在您的示例中,
y
无法访问
x
@IvanSmirnov的私有方法,原始代码片段的目的是允许
x
的成员访问
y
的私有数据。啊,没错,这不是最直观的事情。谢谢,明白了。@IvanSmirnov你建议的是hvd下面的方法,这似乎是不必要的复杂。
class x {
    void xx() {}
};

class y {
    friend x;
};