Possible Duplicate:
When should you use 'friend' in C++?
I have come to a stumbling block because of lack of documentation on friend classes. Most books just explain it briefly, e.g an excerpt from C++: the Complete Reference:
Friend Classes are seldom used. They are supported to allow certain special case situations to be handled.
And frankly, I have never seen a friend class in any good code made by an experienced C++ programmer. So , here is my list of problems.
Do Inherited Classes have the same friends as there base classes? e.g, if I declare class foo as a friend of class base, will class der
(derived from base) also have foo as a friend?
What are the special case situations when a friend class should be used?
I am making a winapi wrapper in which I want to make class WinHandle a friend of class Widget (to access some protected members). Is it recommended? Or should I just access them using the traditional Get/Set functions?
In general, friend classes are useful in designs where there is intentional strong coupling: you need to have a special relationship between two classes. More specifically, one class needs access to another classes's internals and you don't want to grant access to everyone by using the public access specifier.
A friend class in C++ can access the private and protected members of the class in which it is declared as a friend. A significant use of a friend class is for a part of a data structure, represented by a class, to provide access to the main class representing that data structure.
Use of Friend Class in C++Accessing private and protected members of other classes (as you would know by now) Declaring all the functions of a class as friend functions. Allowing to extend storage and access its part while maintaining encapsulation. Enabling classes to share private members' information.
Benefits of friend function A friend function is used to access the non-public members of a class. It allows to generate more efficient code. It provides additional functionality which is not normally used by the class. It allows to share private class information by a non member function.
Friend is used for granting selective access, just like the protected access specifier. It's also hard to come up with proper use case where use of protected is really useful.
In general, friend classes are useful in designs where there is intentional strong coupling: you need to have a special relationship between two classes. More specifically, one class needs access to another classes's internals and you don't want to grant access to everyone by using the public access specifier.
The rule of thumb: If public is too weak and private is too strong, you need some form of selected access: either protected or friend (the package access specifier in Java serves the same kind of role).
For instance, I once wrote a simple stopwatch class where I wanted to have the native stopwatch resolution to be hidden, yet to let the user query the elapsed time with a single method and the units to be specified as some sort of variable (to be selected by user preferences, say). Rather than, have say elapsedTimeInSeconds()
, elapsedTimeInMinutes()
, etc. methods, I wanted to have something like elapsedTime(Unit::seconds)
. To achive both of these goals, I can't make the native resolution public nor private, so I came up with the following design.
class StopWatch;
// Enumeration-style class. Copy constructor and assignment operator lets
// client grab copies of the prototype instances returned by static methods.
class Unit
{
friend class StopWatch;
double myFactor;
Unit ( double factor ) : myFactor(factor) {}
static const Unit native () { return Unit(1.0); }
public:
// native resolution happens to be 1 millisecond for this implementation.
static const Unit millisecond () { return native(); }
// compute everything else mostly independently of the native resolution.
static const Unit second () { return Unit(1000.0 / millisecond().myFactor); }
static const Unit minute () { return Unit(60.0 / second().myFactor); }
};
class StopWatch
{
NativeTimeType myStart;
// compute delta using `NativeNow()` and cast to
// double representing multiple of native units.
double elapsed () const;
public:
StopWatch () : myStart(NativeNow()) {}
void reset () { myStart = NativeNow(); }
double elapsed ( const Unit& unit ) const { return elapsed()*unit.myFactor; }
};
As you can see, this design achieves both goals:
I really like this design because the original implementation stored the multiple of native time units and performed a division to compute the elapsed time. After someone complained the division was too slow, I changed the Unit
class to cache the dividend, making the elapsed()
method (a little) faster.
In general, you should strive for strong cohesion and weak coupling. This is why friend is so little used, it is recommended to reduce coupling between classes. However, there are situations where strong coupling gives better encapsulation. In those cases, you probably need a friend
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With