views:

1395

answers:

10

Some programmer said that, "a friend function break the encapsulation in C++". and some programmer also said, "Friend functions do not break encapsulation; instead they naturally extend the encapsulation barrier"

what does it mean?..

If a friend function breaks the encapsulation in C++ then how??

A: 

The friend keyword allows other classes to access private and protected data members in C++. Some people think this is breaking encapsulation, other people think that it's extending encapsulation to a small number of outside classes that need access to private/protected data. The "breaking encapsulation" means that members and methods are usually private for a reason, and the friend keyword breaks that encapsulation.

In the code I've seen the friend keyword usually breaks encapsulation and reduces code quality, but there are occasionally situations in which it's used well.

Here's a simple tutorial on class friendship and inheritance if you've never seen it before:

Friendship and Inheritance

James Thompson
A: 

As soon as you declare a friend function, access specifiers, and thus, encapsulated details of your class will become accessible by that friend function, which is not a part/method of your class. So, you basically delegate some control over internal data structures and methods to an external function that you 'trust'

none
A: 

If you draw a line around everyone who can access private data, that is the extent that the data is encapsulated.

If you use the friend keyword, that line has to be drawn around more things. Thus encapsulation is extended or broken, depending on your point of view.

In general, I discourage the use of friend. Instead consider adding accessors for private data.

jeffamaphone
Around more things? Surely it has to be drawn around the exact same number of functions. The only question is whether they're part of the class or not.
jalf
+2  A: 

You have two different schools of thought.

The first one (Java & C# ...) :: throw every function in the public area of the class, whether that function 'needs' to access the 'private' area or not.

The second one (C++ ...) :: provide 'only' the needed functions so this class can survive, and provide higher level functions in unrelated collection of the created type.

IMHO :: C++ satisfies OOP goals clearly.

AraK
How is Java throwing every function in the public area? If you define a function private and only the functions needed from outside public then OOP Goals are satisfied I think.
Janusz
@Janusz: Public area as opposed to outside the class. He's not talking about private functions, but about the ones that need to be publicly visible. C# and Java says they should all go in the class, C++ says as few as possible of them should go in the class, and the rest should be nonmember functions.
jalf
@jalf, well that admittedly yields to a better coupling, theoretically. But in practice, i find it inconvenient to change back and forth between member function call syntax and free function call syntax. As Scott writes (i linked in the comment to main question), for functions that are important, it may still be viable to write them as member functions, even though they *could theoretically* non-member non-friend functions. In my opinion, the whole point *for me* about non-member functions is to make use of koenig lookup (As described my Herb Sutter "What's in a Class?").
Johannes Schaub - litb
While i would make certain functions non-member non-friend ("swap", "size", "begin", "end"), i would also add them as members, in addition. The former functions benefit greatly from Koenig loopup, for example. Another function, like "str" (conversion to string) or operator<<, would only go as non-member non-friend for me because they are less important. (notice how "size" is a member function even though it can be implemented as end - begin, but is still a member function in my model). It depends on the actual case, for me.
Johannes Schaub - litb
In C++, not all functions should be non-members, even according to Scott Meyers: Those that can only be implemented in terms of public functions should go outside the class by default. If you wanna add a public function that an only be implemented in terms of private functions (like ".begin()"), that should still be a member, if i read his paper right. And i actually agree with this.
Johannes Schaub - litb
+6  A: 

Encapsulation means that you can't see what's inside, and friend means that you can see inside. Depending on your point of view, friend therefore either breaks encapsulation (by letting the friend see inside), or extends it (by letting the developer relax the barrier to specific friends only).

FWIW, a good rule of thumb is to say that only nested/inner classes should be declared as friends; this rule can be summarized as "no long-distance friends", i.e. a class's friends (if any) should be declared within the same header file as the class itself.

ChrisW
Interestingly, in Ada that's the only way you can get that functionality. They are called "children". The issue they have is that anyone can create a child after the fact, even if the designer didn't intend for them to. So our similar rule of thumb in Ada to prevent abuse is "no bastard children". :-)
T.E.D.
Similarly in C#.
ChrisW
+1 for the "point of view". Many programmers fail to realize the difference in point of view.
Magnus Skog
So what I told you was true..from a certain point of view...
CodeFusionMobile
+10  A: 

The reason some say that "friends" break encapsulation is because the whole point of encapsulating data and functionality is so that nothing else that needs to see that data can, but friends let some other classes see inside.

I personally think friends do not break encapuslation because classes should not be completely dependent, but rather interdependent.

Take the analogy of a car. We typically use this as a model of abstraction, saying we don't need to know how the engine works to know that pushing the gas pedal makes it go. This is the whole idea of encapsulation, where only the functions we need to interact with a class are the only ones we need to know about.

However, a Mechanic class would definately need to know about the specific inner workings of the car, but it makes no sense to build a Mechanic into a Car.

This is where friends come in. You make the Mechanic a Friend of the engine, the brakes, or whatever needs to be fixed and he can fix it. He can't fix it if all he can do is press gas/brake.

CodeFusionMobile
This is where you want Cars to implement an interface Driveable, which has a method "InternalCombustionVehicle ". The inner workings needn't be private (indeed on my car they aren't - I can pop the hood myself and I know nothing about engines). But if you haven't read the docs / trained as a mechanic, the InternalCombustionVehicle interface isn't much use or interest. Still, "friend" is of use in the rare case where the car knows every mechanic an can authorise them explicitly (manufacturer-certified repair centres, to stretch the analogy to breaking point...)
Steve Jessop
Yes, that is the bane of all analogies isn't it. Stretching to the breaking point by definition means that the analogy no longer works.
CodeFusionMobile
It still just about works to the extent that when you change the private interface (engine), your friends (certified repair centres) gives a finite list of things that have to be updated with the changes. Nobody else needs to know. When you change InternalCombustionVehicle, every user (backyard mechanic) needs to know. But using "friend" for this purpose conflates a public/non-public interface with a published/unpublished interface, which is probably a topic for another day.
Steve Jessop
+19  A: 

Quote from C++ FAQ which I think describes the situation with friend and encapsulation very well.

No! If they're used properly, they enhance encapsulation.

You often need to split a class in half when the two halves will have different numbers of instances or different lifetimes. In these cases, the two halves usually need direct access to each other (the two halves used to be in the same class, so you haven't increased the amount of code that needs direct access to a data structure; you've simply reshuffled the code into two classes instead of one). The safest way to implement this is to make the two halves friends of each other.

If you use friends like just described, you'll keep private things private. People who don't understand this often make naive efforts to avoid using friendship in situations like the above, and often they actually destroy encapsulation. They either use public data (grotesque!), or they make the data accessible between the halves via public get() and set() member functions. Having a public get() and set() member function for a private datum is OK only when the private datum "makes sense" from outside the class (from a user's perspective). In many cases, these get()/set() member functions are almost as bad as public data: they hide (only) the name of the private datum, but they don't hide the existence of the private datum.

Naveen
A: 

Friendship promotes cohesion at the expense of some encapsulation. You still have an encapsulated unit (the class and its friends), though it's less granular. But when the alternative is adding extra functionality to the class, that does not necessarily belong, the use of friendship allows you the access you need while still maintaining the cohesiveness of the class. Encapsulation is not the only, or even the most, important principle of OOP.

Nick Lewis
+4  A: 

I post a fragment from Stroustrup's The Design and Evolution of C++,

2.10 The Protection Model, pg. 53.
[...]

A friendship declaration was seen as a mechanism similar to that of one protection domain granting a read-write capability to another. It is an explicit and specific part of a class declaration. Consequently, I have never been able to see the recurring assertions that a friend declaration "violates encapsulation" as anything but a combination of ignorance and confusion with non-C++ terminology.

Nick D
+1  A: 

You can think of C++ as having a very primitive access control system - either you can access all members (friend or member function), or you can access only public members (everything else, except...) or you can access public and protected members (...special rules for inheritance).

"Encapsulation" in the abstract is likewise a primitive access control system, except that usually we say that code which is "part of the class" is privileged and can manipulate the object in all the ways the language allows. Code which is not "part of the class" is unprivileged and must use a smaller, probably published, public interface.

So, what is "friend" for? If you think of things this way, it's for writing privileged code which is not a member function. It's necessary because there are some things which for technical reasons cannot be member functions. The ones I can think of off-hand are operator overloads where you need conversion on the LHS, and specializations of standard algorithm template functions like std::swap (the latter being less of an issue, since if there's a public swap function, it's unlikely to be harmful for there to be a public swap method too. But it's nice to support those folks who want interfaces to be orthogonal).

The question then is, does it break encapsulation to have privileged code which is not a member function? In Java you'd probably say "yes", since Java code is clearly "part of the class" if it's in the class definition, and not part of the class if it's not.

In C++ it's a bit less clear, since member functions definitions don't have to be in the class definition to start with. There's very little difference between:

// Foo.h
class Foo;
void bar(Foo &);

class Foo {
    friend void bar(Foo &);
public:
    static void baz(Foo &);
};

// Foo.cpp
void bar(Foo &f) {
    // access private members of f
}
void Foo::baz(Foo &f) {
    // access private members of f
}

I cannot convince myself that in any meaningful sense bar "breaks encapsulation" whereas baz "preserves encapsulation". Even a tiny degree of pragmatism indicates that bar and baz are doing exactly the same thing, and furthermore that even though bar is not a member function, it clearly is "part of the class" just as much as baz is. The only differences are syntactic, and have nothing to do with encapsulation.

On the other hand, clearly "friend" can be used to completely break encapsulation, by naming every other class you can think of as your friend (like making all your members public or package protected in Java, or making all your members public in C++). "friend" does need to work with classes and not just methods, so that you can declare nested classes as friends where appropriate, and have small clusters of tightly-coupled classes which aren't nested (which is to say: draw the bounds of encapsulation at a higher level than that of a single class). If you use it to tightly couple all your classes, then you'll probably end up with bad code.

This isn't really because of "friend", since all that has done is given me a new syntax to expose members that I could have exposed as "public" anyway. But if I reach for "friend" as a workaround, and use it to break through my own inadequate public interfaces, then "friend" has in effect given me an excuse for poor design. I might swear off it in future, and advise others to do likewise, but this is for the same reason I swear off drink every time I wake up hung over. Others may be wise or lucky enough to enjoy the benefits without major side-effects.

So "friend", in and of itself allows encapsulation-breaking, just like pointer arithmetic does, and just like alcohol allows falling into the gutter at 3am. With care and decent design, however, particular uses of friend should not and need not be encapsulation-breaking. And, in case any potential future employers are reading this, when I drink I'm not normally hung over ;-)

Ultimately the issue is that in every language I know, interfaces behave like inheritance, in the sense that the class's public interface incorporates all the members of all the interfaces it implements. The class interface is therefore larger than any other. This is no a bad thing, since the "is-a" relationship is key to OO. Furthermore, it corresponds well with what happens which you publish an interface, which is that any client might be using it. It just doesn't naturally accommodate what a lot of designs call for, which is for classes by default to have a small interface, but to also offer a larger interface to "superusers". So instead the large interface is the default, and "subusers" stick to the boring parts.

So, friend is one blunt tool for offering a larger interface to "superusers" without affecting the "subuser" interface. Since it is so blunt, though, it really only works when the relevant classes are all designed together, and arguments about how coupled classes ought to be is what leads to disagreements as to what "breaks encapsulation". Remember that access levels in languages aren't supposed to enforce encapsulation, and C++ in particular is a multi-paradigm language. So C++ makes some effort to assist programmers in enforcing encapsulation, but the programmer still has to design well, and use the available features in accordance with his own programming principles.

Steve Jessop