Dan Nestor
Dan Nestor

Reputation: 2531

Alternative to friendship?

Is there any alternative to friendship in the following scenario?

I have a Window class which represents an UI window. Also, a WindowManager class, implemented as a singleton, manages all window objects in my application (renders the UI, dispatches events, etc.)

The WindowManager will have a public interface consisting of only its singleton instancing method and functions to render the UI and to dispatch an UI event.

I would also like Window objects to register with the WindowManager during construction and to de-register during destruction. The WindowManager::register and WindowManager::deregister methods will be either private or protected, because I do not want clients (other than Window objects) to be able use this interface.

Is there a method to avoid friendship between Window and WindowManager in this case? Perhaps a totally different way to achieve similar results?

Upvotes: 4

Views: 4466

Answers (5)

Marcin
Marcin

Reputation: 917

Another solution (not necessary better :]) is to put the window registration to a separate component - let's say the WindowRegister. WindowRegister can have a public interface for registration and can also be a private member of a WindowManager.

The problem with friendship is that it is not inherited (a friend of my grandpa is not necessary my friend) - and there is a big chance that either Window or WindowManger will be polymorphic.

Regards

Upvotes: 2

Keith Irwin
Keith Irwin

Reputation: 5668

There are several other options. For example:

  • You could use pointer math, assembly code, and knowledge about the layout of the classes in memory to call private methods at runtime. This, however, is not very portable.
  • You could make the method public, but require that it take a parameter cryptographically signed by a private key which lives in the Window class, thus preventing other classes from being able to actually call the method and have it do anything.
  • You could make the method protected and make one inherit from the other.
  • You could make a common superclass which they both inherit from and use protected methods from it to communicate between them.
  • You could use the little used "enemy" keyword to allow them to run each other's private methods, but only when they have blackmail material which incriminates the other class. (Okay, that's not a real language feature, but it should be.)

Or you could just make them friends. That's much easier and saner than any of the other options and why friends exist.

Upvotes: 1

Ben Voigt
Ben Voigt

Reputation: 283733

Yes, but friendship is the best solution, since it's designed for this scenario.

Another way is to make Window a member of WindowManager (note, this requires the new C++11 accessibility rules). Or have it derive from a member of WindowManager. Or have it derive from WindowManager itself.

You can also put a private type inside Window, make a key type nested in Window which can only be constructed from that private type, and require passing an instance of that key type to WindowManager. This should work in pre-C++11 compilers.

Of course, any approach can be bypassed using enough casting.

Upvotes: 4

Pubby
Pubby

Reputation: 53067

Use nested classes.

WindowManager {
  private:
    static void construct();
    static void destruct();
  public:
    class InternalWindow { // can access WindowManager's private members (no scoping needed)
      InternalWindow() { construct(); }
      ~InternalWindow() { desstruct(); }
    };
};

typedef WindowManager::InternalWindow Window; // to make scoping easier

Upvotes: 2

Alok Save
Alok Save

Reputation: 206566

Using Friendship seems appropriate here.You want to indicate an Intentional strong coupling between the two classes, which is aptly indicated through friends.

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: is public is too weak and private is too strong, you need some form of selected access: either protected or friend.

Using Friendship is the Best solution here.

Upvotes: 2

Related Questions