Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Here is my situation (a simple example).

Say I have a class called HiddenData
Then I have another class called StoreHiddenData
And finaly a class called OperateHiddenData

Here's the thing, my class called HiddenData has private members that I don't want to be visible to the rest of the world, but I still need classes to be able to operate on private members of this HiddenData class (StoreHiddenData and OperateHiddenData for example). I would like to be able to pass this object around to different classes that do different things on it.

Another thing I was thinking of is to create a form of handle to these HiddenData objects, but I can't think of a way to use handles without using friend classes again (as to give the other classes access to a table that contains what the handles point to, without exposing it to the rest of the world as well).

I was reading this question on this site just a while ago as I was researching the use of friend classes, and it has me thinking if using friends is the best way to go.

If anyone has any suggestions for how to accomplish this task without the use of friend classes in C++, or if the use of friend classes is an OK OOP practice, please provide me with any suggestions. Thanks.

EDIT: I figure I should add a little bit more information about my problem. For one thing, I am trying to create an API that consists of several classes that hide their functionality from the outside and only allow public functions to be accessed. On the inside I have data structures (or classes, doesn't really matter), that need to be passed around to these different classes with public functions. I don't want the outside to have access to anything inside these data structures other than being able to pass them around to functions of the API. I kind of think of it like the Windows API, where you pass around Handles to API functions, but you can't actually dissect the handles in your own code. Well I would like to do something very similar, but while remaining object oriented, and NOT passing these private data structures around by value because they will be BIG. Thanks again.

share|improve this question
    
I don't see why not - that's what friend classes are for. I mainly work with Java, and there are times I wish I could do that. –  Mike Baranczak Jan 29 '12 at 18:37
1  
To add to @MikeBaranczak - there are several examples of good use of friend in C++. For example, the Iterator design pattern can use friend to access private members so that the aggregate (the thing being iterated over) doesn't have to expose methods for the sole purpose of iteration. It lets you keep iteration methods in the iterator and data structure maintenance methods in the data structure. Using friend to accomplish similar goals is probably a good use of the language constructs of C++. –  Thomas Owens Jan 29 '12 at 19:13
1  
Ok, here's the deal: Every tool has a variety of tricks available. Friend classes do indeed make private members available to other classes. However, to answer your question, I need to learn more about the nature of the problem. Can you broadly describe the scenario and why you think encapsulation of the form described above is appropriate? –  Stephen Gross Jan 29 '12 at 23:16
    
@StephenGross: I don't really know how else to explain it. I have an object that I only want a few functions of to be exposed to the rest of the program, except for the few classes that have functions that take that object as a parameter and operate on private members. I want these objects to be passed around anywhere in the program, and have a limited number of functions available, but for the most part they hold data I want only to be accessible to a few components of the program. –  jacobcase94 Jan 30 '12 at 1:34
    
@JAKE6459: If you have few functions that you want to expose to everyone, put those functions into an interface (abstract virtual no-implementation base class) and pass that interface type around your whole app. Then have your "special" code use the object directly through well-defined public class interface. –  DXM Jan 30 '12 at 3:29
show 1 more comment

2 Answers

up vote 4 down vote accepted

I would be extremely cautious about the use of friends. Although friends, have their time and place, most of the time when people use them, it's only as a convenient way of breaking encapsulation, which makes the code easy to write and deliver v1.0 but as the number of classes that operates on your HiddenData increases and as the average size of those classes increases, it will become a nightmare to read and modify.

I've used friends a few times, but only when alternatives would've been even uglier/harder to maintain. Iterators which are associated with a specific collection is definitely a good example of using friends.

Another example is implementations of finite state machines(FSM), where each state is represented by a separate class. Here your FSM is your real class, the states are just a way of splitting up logic into manageable units, but generally the data still belongs to FSM.

Bottom line, I would lean towards friends if second class is extremely small and won't be extended with more and more functionality with each release. Also the placement of the two classes should be as close as possible to one another. In case of STL's iterators, those classes are defined right inside their own container classes. Don't get any closer than that.

There are several ways of implementing your scenario while not having to break encapsulation by using friends. Here's only few of many alternatives:

  1. Have HiddenData be truly hidden. Don't freely give out reference to it. Instead have another adapter/view/decorator (whatever you want to call it) class between the data and the public. This other class would ensure that only public operations are allowed. Then your special manipulator classes would access normal public interface of HiddenData directly.

  2. Take a look at Visitor Pattern. It might be exactly what you need. It give you the ability to add functionality to a class without actually touching the class itself. So to implement another special manipulator which has access to internal data, you would create a new visitor class and give a reference to a single Accept() method of the HiddenData.

share|improve this answer
5  
friend don't break encapsulation for a very simple reason: a class cannot become friend of another without the other wants it. The friends, together, are just another bigger "capsule". –  Emilio Garavaglia Jan 30 '12 at 8:40
    
@EmilioGaravaglia: friend is a way to break encapsulation "locally". If I write an application which contains 20 classes and all data is private, but these class all happen to be friends with each other. Would you consider encapsulation to be preserved? Maybe all data is private, but I can tell you right now that app will be a royal PITA to maintain, just like one which has no encapsulation. So if you have a larger app with 500 classes, but 20 of them happen to be friends, as those 20 grow and morph and get touched by multiple developers, you will experience exactly the same pains –  DXM Jan 30 '12 at 9:11
    
@DXM: "local" encapsulation is an artefact of the fact, that in OOP class triples as a data type, unit of code reuse and unit of encapsulation, but it does not always make sense. When it does not, you define the unit of encapsulation with friends. If you have 20 classes that are mutual friends, you have the same problem as if you had one class with the same amount of code. It is simply bad design and does not say anything about friend being evil. –  Jan Hudec Jan 30 '12 at 11:20
    
@JanHudec: I never said they were evil and as I mentioned, I used them myself time to time. But when I see other people discover friend keyword, 9/10 times it is because they couldn't come up with a better, cleaner, easier to maintain design that didn't require that keyword. It is not evil but it is dangerous and should be used with care, not as pretend-encapsulation. This question is case in point. It seems the OP simply needs an interface that exposes the limited set of public functionality and he can just pass that interface around. –  DXM Jan 30 '12 at 14:51
1  
@DXM: C++ is a "pragmatic language". And "pragmatism" is not for Talibans. If you have 20 classes all each other friend and you know what have you done, your mess it's up to you. But you are always granted that I -using your classes with my own classes- will never be able to mess up your "private parts". Whatever mess they can be / have themseves. The "encapsulation", in a pragmatic language, is no more than that. Be sure nothing external to a context can mess up things inside. How wide a context should be, and how many things should contain is a matter of design, not of keywords. –  Emilio Garavaglia Jan 30 '12 at 18:28
show 4 more comments

C++ friends exist just for that. Every other surrogate will simply mimic the same concept.

  • There are thing that are for everyone,
  • Things for you only, (eventually inherited from your children)
  • Things shared by you with a well define and limited set of people.

Those "people" are called "friend". Eliminating that concept will require those things to become public, or to become private, but with public accessors to be managed. You must also expect anyone to be capable of doing things with them out of your control.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.