为啥在 A 类中声明为友元的函数必须在 B 类中定义为公共函数?

Posted

技术标签:

【中文标题】为啥在 A 类中声明为友元的函数必须在 B 类中定义为公共函数?【英文标题】:Why must a function, declared as friend in Class A, be defined as a public function in Class B?为什么在 A 类中声明为友元的函数必须在 B 类中定义为公共函数? 【发布时间】:2016-08-01 16:49:39 【问题描述】:

A 类是 B 类实例的容器。

文件 A.h:

#include "B.h"

Class A
   public:
    unique_ptr<B>                       getInstanceOfB();

    private:
    unique_ptr<map<int, shared_ptr<B>>> uptr_BInstancesMap;
    map<string, int>                    map__BUniqueValues;

    friend int                          B::getValueIndex( const string );
;

文件 B.h:

Class B
   public:
    unique_ptr<B>                       returnInstanceOfB();
//  int                                 getValueIndex( const string );  // Compiles fine

    private:
    int                                 int__ValueIndex;
    int                                 getValueIndex( const string );  // "error: 'int B::getValueIndex(std::string)' is private"

可能有超过 100,000 个 B 的实例存储在 A 的实例中,但由 B 的这些实例表示的唯一值会少得多。 所以想法是将唯一值存储在 A 的实例中,并将索引存储到 B 的每个实例中的(共享)值。 对于朋友功能来说,这似乎是一个合理的场景。

getValueIndex() 用于 B 类;它不应该公开。 有人能解释一下(也许是一个危险的例子)为什么朋友函数定义不能是私有的吗?

【问题讨论】:

@Mark Ransom:措辞不佳。 “A类是B类的容器”会更准确吗? 好多了。我现在将删除我的评论。 在 A 类中声明 friend int B::getValueIndex(const string); 使其能够访问 A 类的私有/受保护成员,而不是相反。 德米特里,这正是我想要的。 B::getValueIndex 将操纵 A::map__BUniqueValues。 【参考方案1】:

这里有一个“循环”。

friend in A 表示声明的函数可以访问 A 的私有部分。

但是要访问该声明,A 本身必须可以访问它,因此 B 必须有 A 作为朋友。

我理解你对“纯粹”的愿望,但 C++ 完全不是一种“纯粹”的语言。如果 A 和 B 密切相关,并且您对它们都负责,那么与其疯狂地声明,不如让它们成为彼此的朋友。

除了他们之外,没有人可以做任何危险的事情,而您已经处于自己的“危险区域”,您已经知道......那么为什么会出现并发症?

【讨论】:

将“朋友 A 类”添加到 B 类就可以了!我还不明白“要访问该声明,A 本身必须可以访问它”,但这是我的猜测:A 类中的友元函数声明告诉编译器 A 想要授予 B::getValueIndex() 访问权限到它的私有成员,但编译器拒绝,因为 B::getValueIndex() 是私有的,A 甚至不允许知道它在那里。将“朋友类 A”添加到 B 类会授予 A 访问 B 的私有成员的权限 - 包括 B::getValueIndex() - 因此编译器现在可以让该函数访问 A 的私有成员。 确切地说:私人超过私人需要双重“有利益的朋友”......;-)【参考方案2】:

我的看法:

私有方法应该是可以随意改变的,在类之外没有影响。如果您将B 的私有方法设为A 的朋友,则该私有方法的签名签名不能在不更改A 的情况下更改。

【讨论】:

Arkadiy:但是如果您对 A 的私有成员进行更改(例如重命名),则必须更改 B 中的友元函数。在我看来,使用友元函数隐含地承认需要更改两个类。 没有对方想要的,谁也不能成为对方的“朋友” 当 B 是 A 的朋友时,您承认当 A 的私人成员发生变化时 B 也必须发生变化。但是 - 不是相反。 A 不知道 B 的私有成员。 Arkadiy:我的意图是 B::getValueIndex() 将访问 A 和 B 的私有成员。A 无意访问 B 中的任何内容。但 Dmitri 也这么认为我的代码中一定有一些东西表明 A 将尝试访问 B。是否在函数签名中缺少对 A 实例的引用? 如果您将友元函数设为私有,则根据定义,A 知道 B 的一个私有函数(友元声明中引用的那个)。我认为 C++ 标准编写者认为这是不可取的,所以朋友函数必须是公开的。这是一个非常薄弱的​​理由,但我现在能想到的最好的理由。

以上是关于为啥在 A 类中声明为友元的函数必须在 B 类中定义为公共函数?的主要内容,如果未能解决你的问题,请参考以下文章

5.友元运算符重载

C++友元函数 普通函数声明为友元函数

C++友元函数 普通函数声明为友元函数

C++友元函数 普通函数声明为友元函数

友元在类中的使用

友元函数都有哪些特点?