views:

162

answers:

3

I want to make a class A friend class of class B. I want to do this as these interact very much and A needs to change internals of class B (which I dont want to expose using public). But I want to make sure it has access to only a few selected functions not all the functions.

Example:

class A
{
};

class B
{
private:
 void setState();
void setFlags();
friend class A
};

I want A to be able to access setState but not setFlags... Is there a design pattern or a nice way of doing this or am I left with giving full access or no access at all in this case.

Thanks

+14  A: 

It depends on what you mean by "a nice way" :) At comp.lang.c++.moderated we had the same question a while ago. You may see the discussion it generated there.

IIRC, we ended up using the "friend of a nested key" approach. Applied to your example, this would yield:

class A
{
};

class B
{
public:
     class Key{
         friend class A;
         Key();
     };

    void setFlags(Key){setFlags();}         

private:
  void setState();
  void setFlags();
};

The idea is that the public setFlags() must be called with a "Key", and only friends of Key can create one, as its ctor is private.

Éric Malenfant
+1: I haven't seen this before - really very clever.
Richard Corden
Really clever. I usually relied on a 'contract' since I had not fought of any way to this... you learn every day!
Matthieu M.
By the way, in the OP question, he wanted to access setState, not setFlags... yes I am pedantic...
Matthieu M.
I've been thinking about it... why make Key a nested class of B ? Doesn't it prevent forward declaration and thus provokes a dependency (A's header will need to include B's header to have Key) ? I think perhaps using a nested namespace here (the famous detail) could be better.
Matthieu M.
+6  A: 

One approach is through explicit interfaces, because the implementor of an interface can select who they give them to:

class NearlyPrivateInterface {
public:
   virtual void setState() = 0;
   virtual void setFlags() = 0;
};

class A {
public:
   void attach(NearlyPrivateInterface* instanceOfB);
};

class B: private NearlyPrivateInterface {
public:
   void attach(A& a) { a.attach(this); }
};
Will
That the private interface pattern: http://www.objectmentor.com/resources/articles/privateInterface.pdf
Éric Malenfant
+1  A: 

You can do following thing..

class A{
};

class B{
private: 
    void setFlags();
protected:
    void setState();

}; 

class RestrictedB :public B{  
    friend class A;
};
Ashish