C++ – Should Friend Classes Be Used to Allow Access to Hidden Members?

cfriendsobject-oriented

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.

Best Answer

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.

Related Topic