何时在 C++ 中使用友元类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/521754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use friend class in C++
提问by GBa
Possible Duplicate:
When should you use 'friend' in C++?
可能的重复:
什么时候应该在 C++ 中使用“朋友”?
I was brushing up on my C++ (I'm a Java developer) and I came across the friend class
keyword which I had forgotten about for a while. Is this one of those features that's just part of the kitchen sink, or is there a good reason for doing this rather than just a vanilla getter? I understand the difference in that it limits who can access the data, but I can't think of a scenario when this would be necessary.
我正在复习我的 C++(我是一名 Java 开发人员),我遇到了friend class
一个我已经忘记了一段时间的关键字。这是只是厨房水槽一部分的功能之一,还是有充分的理由这样做而不仅仅是香草吸气剂?我理解不同之处在于它限制了谁可以访问数据,但我想不出有必要这样做的场景。
Note: I've seen a similar question, but specifically I'm asking, is this just an advanced feature that adds no real value except to confuse people looking at you're code until they realize what you're doing?
注意:我看到了一个类似的问题,但我特别想问的是,这只是一个高级功能,除了混淆那些看着你的代码的人,直到他们意识到你在做什么之外,它没有增加任何真正的价值吗?
回答by John D. Cook
I agree with the comments that say the friend keyword can improve encapsulation if used wisely. I'd just add that the most common (legitimate!) use for friend classes may be testing. You may want a tester class to have a greater degree of access than other client classes would have. A tester class could have a good reason to look at internal details that are deliberately hidden from other classes.
我同意一些评论,如果使用得当,friend 关键字可以改进封装。我只想补充一点,朋友类最常见(合法!)的用途可能是测试。您可能希望测试人员类具有比其他客户端类更高的访问权限。测试人员类可能有充分的理由查看故意对其他类隐藏的内部细节。
回答by James Thompson
In my experience, the cases when friend (or mutable, which is a little similar) to actually enhance encapsulation of data are rare compared with how often it's used to break encapsulation.
根据我的经验,与用于破坏封装的频率相比,friend(或 mutable,有点相似)实际增强数据封装的情况很少见。
It's rarely useful to me but when I do use it it's for cases in which I've had to split a class that was formerly a single class into two separate classes that need to access some common data/functionality.
它对我很少有用,但是当我使用它时,我不得不将一个以前是单个类的类拆分为两个需要访问一些公共数据/功能的独立类。
Edit to respond to Outlaw Programmer's comment: We absolutely agree on this. One other option apart from friend'ing classes after splitting them is to make public accessors, which sometimes break encapsulation! I think that some people think that friendly classes somehow breaks encapsulation because they've seen it used improperly a lot, and many people probably never see code where it's been used correctly, because it's a rare thing. I like your way of stating it though - friendliness is a good middle ground between not allowing you to split up your class and making EVERYTHING accessible to the public.
编辑以回应 Outlaw Programmer 的评论:我们完全同意这一点。除了拆分类之后的友元类之外,另一种选择是创建公共访问器,这有时会破坏封装!我认为有些人认为友好类以某种方式破坏了封装,因为他们已经看到它被大量使用不当,而且很多人可能从未见过它被正确使用的代码,因为这是一种罕见的事情。不过,我喜欢你的表述方式——友好是一个很好的中间立场,介于不允许你分裂你的班级和让公众可以访问一切之间。
Edit to respond to David Thornley: I agree that the flexibility that C++ allows you to do things like this is a result of the design decisions that went into C++. I think that's what it makes it even more important to understand what things are generally good and bad style in flexible languages. Java's perspective is that you should never have friend classes so that these aren't provided, but as C++ programmers it's our responsibility as a community to define appropriate use of these very flexible but sometimes misused language constructs.
编辑以回应 David Thornley:我同意 C++ 允许您做这样的事情的灵活性是 C++ 设计决策的结果。我认为这就是理解灵活语言中哪些东西通常是好的和坏的风格变得更加重要的原因。Java 的观点是,您永远不应该拥有友元类,以便不提供它们,但是作为 C++ 程序员,我们作为社区有责任定义这些非常灵活但有时会被误用的语言结构的适当使用。
Edit to respond to Tom: Mutable doesn't necessarily break encapsulation, but many of the uses of the mutable keyword that I've seen in real-life situations break encapsulation, because it's much more common to see people breaking encapsulation with mutable than to actually find and understand a proper use of mutable in the first place.
编辑以回应 Tom:Mutable 不一定会破坏封装,但是我在现实生活中看到的 mutable 关键字的许多用法都会破坏封装,因为看到人们使用 mutable 破坏封装比使用 mutable 破坏封装要常见得多实际上首先要找到并理解 mutable 的正确用法。
回答by User
When you wish that one class (Factory) be responsible for creating instances of another class (Type). You can make the constructor of the Type private and thus make sure that only the Factory can create Type objects. It is useful when you wish to delegate the checks to some other class which could serve as a validator. Just one usage scenario.
当您希望一个类(工厂)负责创建另一个类(类型)的实例时。您可以将 Type 的构造函数设为私有,从而确保只有 Factory 可以创建 Type 对象。当您希望将检查委托给其他可以作为验证器的类时,它很有用。只有一种使用场景。
P.S. Really missing the "friend" keyword in C#...
PS 真的缺少 C# 中的“朋友”关键字......
回答by Rob K
A concrete instance would be a class factory, where you want one class to only be created through another factory class, so you make the constructors private, and the factory class a friend of the produced class.
一个具体的实例将是一个类工厂,您希望一个类只能通过另一个工厂类创建,因此您将构造函数设为私有,并将工厂类作为生成类的朋友。
It's kinda' like a 2" 12-point 3/4"-drive socket - not terribly common, but when you need it, you're awfully glad you have it.
它有点像 2" 12 点 3/4" 驱动器插座 - 不是很常见,但是当您需要它时,您会非常高兴拥有它。
回答by Nemanja Trifunovic
Helps with Memento design pattern
有助于Memento 设计模式
回答by Assaf Lavie
回答by Scottie T
I look at the friend
construct as one of those features of the language that should be used in rare occasions, but that doesn't make it useless. There are several patterns that call for making friend
classes, many of them already on this site in that "Related" bar on the right. ====>
我把这个friend
结构看作是在极少数情况下应该使用的语言特性之一,但这并没有让它变得毫无用处。有几种模式需要创建friend
类,其中许多模式已经在本站点右侧的“相关”栏中。====>
回答by Brian Neal
Friendship is used when you have multiple classes and/or functions that work together to provide the same abstraction or interface. The classic example is implementing some kind of numerical class, and all the non-member operator functions (*, -, +, <<, etc) are given friendship so that they can work on the private data of the numerical class.
当您有多个类和/或函数一起工作以提供相同的抽象或接口时,使用友谊。经典的例子是实现某种数值类,所有非成员运算符函数(*、-、+、<<等)都被赋予了友好关系,以便它们可以处理数值类的私有数据。
Such use cases are somewhat rare, but they do exist, and friend is very useful.
这样的用例有点少见,但确实存在,并且朋友非常有用。
回答by Cory Klein
Here is one example, of several, I'm sure, where a friend class can be legitimately used without disregarding the reasons for encapsulation.
这是一个例子,我敢肯定,可以合法地使用友元类,而无需考虑封装的原因。
MyClass inherits from GeneralClass. MyClass has gotten big, so you created HelperClass to encapsulate some of the function of MyClass. However, HelperClass needs access to some protected functions in GeneralClass to properly perform it's function, so you make HelperClass a friend to MyClass.
MyClass 继承自 GeneralClass。MyClass 变大了,所以你创建了HelperClass 来封装MyClass 的一些功能。但是,HelperClass 需要访问 GeneralClass 中的一些受保护的函数才能正确执行其功能,因此您使 HelperClass 成为 MyClass 的朋友。
This is better than exposing the protected functions, because they don't need to be available to everybody, but it helps keep your code organized in an OOP way to keep MyClass from getting too complex. It makes sense, because although HelperClass isn't concretely related to MyClass by inheritance, it does have some sort of logical connection to it, embodied in the code, and in design, as "friend".
这比公开受保护的函数要好,因为它们不需要对每个人都可用,但它有助于以 OOP 方式组织您的代码,以防止 MyClass 变得过于复杂。这是有道理的,因为虽然 HelperClass 没有通过继承与 MyClass 具体相关,但它确实与它有某种逻辑联系,体现在代码中,在设计中,作为“朋友”。
回答by ravenspoint
I always ( and only ) use friend for unit testing private methods. The only other way I can imagine to do this would be to load up the public interface with a whole lot of testing methods, which is just too messy and so I prefer to hide the test methods in a seperate test class.
我总是(并且只)使用朋友来对私有方法进行单元测试。我能想象的唯一另一种方法是使用大量测试方法加载公共接口,这太混乱了,所以我更喜欢将测试方法隐藏在单独的测试类中。
Something like this:
像这样的东西:
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;
}
};