friend class with limited access
Asked Answered
E

4

14

I want to make class A friend of class B. I want to do this as these interact very much and A needs to change internals of class B (which I don't 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?

Equinox answered 22/10, 2009 at 19:34 Comment(1)
Apart from the fact that you could customize your account (there are so many unknown...), that's a very interesting question indeed. I am still toying with the Key and the Private Interface at the moment!Charactery
K
31

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 setState(Key){setState();}         

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

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

Kilmer answered 22/10, 2009 at 19:39 Comment(5)
Really clever. I usually relied on a 'contract' since I had not fought of any way to this... you learn every day!Charactery
By the way, in the OP question, he wanted to access setState, not setFlags... yes I am pedantic...Charactery
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.Charactery
Is there a way to restrict friends' access on a few data members, rather than method members as described in this solution?Alvarez
Damn that's brilliant!!Perfervid
A
7

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); }
};
Asyndeton answered 22/10, 2009 at 20:1 Comment(1)
That the private interface pattern: objectmentor.com/resources/articles/privateInterface.pdfBorodino
S
1

You can do following thing..

class A{
};

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

}; 

class RestrictedB :public B{  
    friend class A;
};
Seguidilla answered 22/10, 2009 at 21:0 Comment(0)
B
0

You can also use function pointers to accomplish this:

class B
{
    void setState();
    void setFlags();

public:
    class visitor
    {
        static constexpr auto setState = &B::setState;
        friend class A;
    };
};

class A
{
    void doStuff(B& b) { (b.*B::visitor::setState)(); }
};

Or, if you don't mind duplicating function pointers inside A, you can make the syntax look almost normal:

class A
{
    static constexpr auto setState = B::visitor::setState; 
    void doStuff(B& b) { (b.*setState)(); }
};

Example link: https://godbolt.org/z/Thvb6cY5s

Burstone answered 15/7 at 21:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.