在什么情况下应该将成员函数声明为友元?
在什么样的场景下,我们会将成员函数声明为“友元函数”?...“友元函数”违背了 OOP 的“封装”的核心概念之一,其确切目的是什么?
In what kind of scenarios would we declare a member function as a 'friend function' ?..What exact purpose does 'friend function' which defies one of central concept of 'Encapsulation' of OOP serve?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用友元函数的原因与使用友元类的原因相同,但基于成员函数(而不是整个类)。 此线程中有一些很好的解释。
虽然友元函数和类确实违反了封装,但它们在某些情况下可能很有用。 例如,您可能希望允许测试工具访问类内部,以允许您进行白盒测试。 您可以打开一个特定的函数来访问测试工具所需的内部结构,而不是向测试工具开放整个类。 虽然这仍然违反了封装性,但它比开放整个类的风险要小。
另请参阅本文,了解有关友元类和函数的更多信息。
You would use a friend function for the same sort of reasons that you would use a friend class, but on a member function (rather than entire class) basis. Some good explanations are in this thread.
While friend functions and classes do violate encapsulation, they can be useful in some scenarios. For example, you may want to allow a test harness to access class internals to allow you to do whitebox testing. Rather than opening up the entire class to the test harness, you could open up a particular function which accesses the internals required by the test harness. While this still violates encapsulation, it's less risky than opening up the entire class.
Also see this article for some more information about friend classes and functions.
当您尝试构建必须物理上跨越多个 C++ 类或函数的抽象或接口时,友元函数和类不会违反封装! 这就是朋友被发明的原因。
这些类型的情况并不经常出现,但有时您被迫使用不同的类和函数来实现抽象或接口。 典型的例子是实现某种类型的复数类。 非成员运算符函数与主复数类具有友好关系。
我还记得在 C++ 中使用 CORBA 编程时这样做过。 CORBA 迫使我使用单独的类来实现 CORBA 仆人。 但对于我们软件的特定部分,我需要将它们结合在一起作为一个界面。 友谊允许这两个类一起工作,为我们软件的一部分提供无缝服务。
能够将另一个类上的特定成员函数标记为你的类的朋友可能看起来更奇怪,但这只是严格控制友谊的一种方法。 您只允许其成员函数之一访问,而不是允许整个其他类作为您的朋友“加入”。 同样,这并不常见,但是当您需要它时非常有用。
Friend functions and classes do not violate encapsulation when you are trying to build an abstraction or interface that must physically span multiple C++ classes or functions! That is why friend was invented.
Those types of cases don't come up often, but sometimes you are forced to implement an abstraction or interface with disparate classes and functions. The classic example is implementing some type of complex number class. The non-member operator functions are given friendship to the main complex number class.
I also recall doing this when programming with CORBA in C++. CORBA forced me to have separate classes to implement CORBA servants. But for a particular part of our software, I needed to marry these together as one interface. Friendship allowed these two classes to work together to provide a seamless service to one part of our software.
Having the ability to mark a particular member function on another class as a friend to your class may seem even stranger, but it is just a way of tightly controlling the friendship. Instead of allowing the entire other class "in" as your friend, you only allow one of its member functions access. Again, this isn't common, but very useful when you need it.
请参阅C++ FAQ Lite:
See C++ FAQ Lite:
有时公共/私人/受保护的保护级别对于现实世界的情况来说还不够。 因此,我们给出了一个小的退出条款,该条款可以提供帮助,而无需使方法公开可访问。
我个人使用它的方式与 Java 使用“包”保护级别的方式相同。
如果我在同一个包中有一个需要访问的类,我会考虑使用friend。 如果它是另一个包中的类,那么我会想知道为什么这个另一个类需要访问并看看我的设计。
Sometimes public/private/protected protection level is not quite enough for real world situations. So thus we give a small get-out clause that helps without having to make methods publicly accessible.
I personally use this the same way that Java uses the 'Package' protection level.
If I have a class in the same package that needs access I will consider using friend. If it is a class in another package then I will wonder why on earth is this other class needing access and look at my design.
我发现相关的一点是:成员类可以访问包含类的私有部分。 有时这可能是比“朋友”更好的选择。
One point that I find relevant: member classes have access to the private parts of the containing class. This may sometimes be a better alternative to "friend".
这是我如何使用友元函数的一个简单、具体的示例:
我有一个游戏,其中每个精灵对象将其信息(如 X、Y 位置)存储为私有成员。
但是,我希望将游戏对象与渲染分开:游戏对象不需要其渲染方式的确切细节。 游戏对象仅存储游戏状态,并且该游戏状态可以以多种不同的方式呈现。
因此游戏对象类有一个友元函数:render()。 render() 函数在游戏对象类之外实现,但它可以根据需要访问 X、Y 位置位置成员来渲染游戏对象。
Here is a simple, concrete example of how I am using a friend function:
I have a game where each sprite object stores its info like X,Y position as private members.
However, I wish to separate the game objects from the rendering: a game object does not need the exact details of how it is rendered. A game object only stores game state, and this game state may be rendered in a number of different ways.
Thus the game object class has a friend function: render(). The render() function is implemented outside the game object class, but it can access the X,Y position position membefrs as needed to render the game object.