3

Function F can be declared a friend of class C, so that it can access private and protected members of that entire class.

But is there a way to allow F access only to a particular member function of C, as opposed to allowing F access to the entire class?

This is why I want to do it.

Community
  • 1
  • 1
Museful
  • 6,711
  • 5
  • 42
  • 68

2 Answers2

5

No you can't.

One workaround would be to put that particular member function in a separate class C2, from which C inherits, and set up the friendship with C2.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    Or C2 could provide a wrapper interface to certain things in C, so you don't have to set up an artificial inheritance hierarchy. – Neil Kirk Nov 06 '15 at 13:29
4

There is no way to do this directly with friendship, but you can achieve a similar effect with a modification of tag-based dispatching:

class C
{
public:
  class AccessTag
  {
    friend class C;
    friend void F();
  private:
    AccessTag() {}
  };

  void functionToAccess(AccessTag)
  {
    std::cout << "Restricted function called!\n";
  }
};

void F()
{
  C c;
  c.functionToAccess(C::AccessTag()); // OK
}

void nonF()
{
  C c;
  c.functionToAccess(C::AccessTag()); // error, nonF cannot access ctor of C::AccesTag
}

The idea is to only allow functionToAccess to be called by those who can construct a C::AccessTag object. And because of its private constructor, C::AccessTag can only be constructed by its friends. These are C (so that it can call functionToAccess itself, as it could any other of its private functions), and F. F cannot access any other non-public members of C, because it is not a friend of C.

You can even have different access tags for different member functions (or groups of member functions).

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 1
    You don't need `C` to be a friend in this example, since it does not create an `AccessTag` on its own. If needed, it could even copy tag objects, since copy operations are implicitly public in `AccessTag`. In addition you can also make the `AccessTag` a (public) member class of `C`, because it is not really a separate entity but belongs to `C` – Arne Mertz Nov 06 '15 at 13:47
  • @ArneMertz I added `C` as a friend simply to keep the default behaviour "a class can call its private functions." But good point about making it a nested class, will amend. – Angew is no longer proud of SO Nov 06 '15 at 13:52