views:

104

answers:

2

Possible Duplicate:
clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom)

I've wanted this a couple times and haven't been able to come up with a decent way to do it.

Say I've got a member function in class A. I want to be able to call that function from an unrelated class B, but not be generally callable. You might say, "Sure, make the function private and declare B to be a friend of A." That's what I've been doing, but it seems a bit overkill. I don't really want to give B access to everything in A, just the one function.

In short: A::func() callable only by class B, but B not declared a friend of A. Possible?

+4  A: 

You could split the interface of A into several pure abstract base classes and then give B a reference to the interface that has the appropriate method. Other classes would only get interfaces that do not contain this method. Keep in mind that this is not very scalable, as the number of interfaces can quickly become very large.

Space_C0wb0y
+5  A: 

One possible way might be to create a trusted class that wraps A::func and pass a wrapper object to B. This again requires the wrapper to be a friend of A, but you only need to manage one such class, while all external classes can make use of the wrapper.

Example:

class Wrapper;

class A {
  private:
    void func();
    /* other methods */

  public:
    Wrapper getWrapper();

    friend class Wrapper;
};

class Wrapper {
  private:
    A &ref;

  private:
    Wrapper(A &obj) : ref(obj) { }

  public:
    void func() {
      ref.func();
    }

  friend class A;
};

Wrapper A::getWrapper() {
  return Wrapper(*this);
}
casablanca
This is a very heavyweight solution, particularly if you need to do it in multiple places. Plus I don't think that C++ templates give you any way to generalize this over different function and class names (though I could be wrong), which means that you'll repeat this for every single function and class tuple that you want to enable.
JSBangs