何时使用C ++中的朋友类

可能重复:
什么时候应该在C ++中使用“朋友”?

我在刷C ++(我是一个Java开发人员),偶然遇到了我忘记的friend class关键字。 这些function之一就是厨房水槽的一部分,还是有一个很好的理由,而不仅仅是一个香草吸气? 我了解它的不同之处在于它限制了谁可以访问这些数据,但是我不能想到这是必要的。

注意:我已经看到了一个类似的问题,但具体而言,我问,这只是一个高级function,除了让人们看着你的代码感到困惑,直到他们意识到你在做什么之外,没有增加真正的价值。

我同意评论说,如果使用明智的朋友关键字可以改善封装。 我只是补充说,最常见的(合法!)用于朋友类可能正在testing。 您可能希望testing者类具有比其他客户端类更高的访问级别。 一个testing人员类可以有一个很好的理由来看看有意隐藏其他类的内部细节。

以我的经验来看,与其用来破解封装的频率相比,朋友(或可变的,有点相似)实际上增强数据封装的情况是罕见的。

这对我来说很less有用,但是当我使用它的时候,我不得不把一个原来是单个类的类拆分成两个需要访问一些公共数据/function的独立类。

编辑来回应“非法”程序员的评论:我们绝对同意这一点。 另外一种select,除了朋友分类之外,还有一个select就是制作公开访问器,有时候会破坏封装。 我认为有人认为友好的类不知怎么的破坏了封装,因为他们已经看到它的使用不当,很多人可能永远也看不到代码被正确使用的地方,因为这是很less见的。 我喜欢你的expression方式 – 友好是一个很好的中间地带,不允许你分裂你的课堂,让所有的东西都可以被公众使用。

编辑回复David Thornley:我同意C ++允许你做这样的事情的灵活性是C ++devise决定的结果。 我认为这就是为什么灵活的语言理解什么是好的和坏的风格更重要。 Java的观点是,你永远不应该有朋友类,所以不提供这些类,但作为C ++程序员,我们有责任定义这些非常灵活但有时被滥用的语言结构的适当使用。

编辑来回应Tom:Mutable不一定会破坏封装,但是我在现实生活中已经看到的mutable关键字的许多用法都破坏了封装,因为看到人们用可变的方式来封装封装比实际上首先find并理解一个适当的mutable的使用。

当你希望一个类(工厂)负责创build另一个类(types)的实例。 您可以使Type的构造函数为private,从而确保只有Factory可以创buildType对象。 当您希望将支票委托给其他一些可以作为validation者的类时,这是非常有用的。 只有一个使用场景。

PS真的想念C#中的“朋友”关键字…

一个具体的实例是一个类工厂,你只需要通过另一个工厂类来创build一个类,这样你就可以使构造函数成为私有的,工厂类成为生成类的一个朋友。

它有点像2“12点3/4”驱动sockets – 不是非常常见的,但是当你需要它的时候,你非常高兴你拥有它。

帮助与纪念品devise模式

关于朋友的FAQ部分: 在这里

FQA关于朋友的部分: 这里

关于朋友的两种不同的观点。

我把这个friend结构看作是应该在极less数情况下使用的语言的特征之一,但是这并不会使它变得毫无用处。 有几种模式需要开设friend课程,其中很多模块已经在本站点右侧的“相关”栏中。 ====>

当你有多个类和/或function一起工作来提供相同的抽象或接口时,使用友谊。 经典的例子是实现某种数字类,并且所有非成员运算符函数(*, – ,+,<<等)都给予了友好的关系,以便他们能够处理数字类的私有数据。

这样的用例是有点罕见的,但它们确实存在,朋友是非常有用的。

这里有一个例子,我可以肯定,其中一个朋友class可以合法地使用,而不必考虑封装的原因。

MyClassinheritance自GeneralClass。 MyClass已经变大了,所以你创build了HelperClass来封装MyClass的一些function。 然而,HelperClass需要访问GeneralClass中的一些受保护的函数来正确执行它的function,所以你把HelperClass变成了MyClass的朋友。

这比暴露受保护的函数要好,因为它们不需要被所有人使用,但是它有助于保持代码以OOP方式组织,从而避免MyClass过于复杂。 这是有道理的,因为尽pipeHelperClass通过inheritance与MyClass没有具体的关系,但是它确实有某种逻辑连接,包含在代码中,而在devise中则是“朋友”。

我总是(也是唯一的)使用朋友进行unit testing私有方法。 我能想象的唯一方法就是使用大量的testing方法加载公共接口,这太杂乱了,所以我更喜欢将testing方法隐藏在单独的testing类中。

像这样的东西:

 class cMyClassTest; class cMyClass { public: ..... private: friend cMyClassTest; int calc(); // tricky algorithm, test carefully }; class cMyClassTest { public: int test_calc() { cMyClass test; .... int result = test.calc(); if( result == 42 ) return 1; return 0; } }; 

friend类意思是我们都知道是从其他类获取variables的值,所以主要用于使用值,所以我们不需要将其他类的值返回给main函数,然后main就可以得到所需的类成员函数,但是它具有问题是一个类是其他类的朋友,那么朋友类应该在该类的下面