When to use friend class in C++ [duplicate]

2019-01-31 17:15发布

Possible Duplicate:
When should you use 'friend' in 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.

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?

11条回答
迷人小祖宗
2楼-- · 2019-01-31 17:48

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.

查看更多
戒情不戒烟
3楼-- · 2019-01-31 17:51

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.

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.

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.

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.

查看更多
乱世女痞
4楼-- · 2019-01-31 17:54
祖国的老花朵
5楼-- · 2019-01-31 17:56

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.

查看更多
仙女界的扛把子
6楼-- · 2019-01-31 17:56

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;
}
};
查看更多
唯我独甜
7楼-- · 2019-01-31 17:57

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.

P.S. Really missing the "friend" keyword in C#...

查看更多
登录 后发表回答