6

Given the sample code:

class Base {
public:
  bool pub;
protected:
  bool prot;
};

class Derived : private Base {
  friend class MyFriend;
};

class MyFriend {
  Derived _derived;

  void test() {
    // Does standard provide me access to _derived.pub and _derived.prot?
    cout << "Am I allowed access to this: " << _derived.pub
         << " and this: " << _derived.prot;
  }
};

Does being a friend give me all access I would get as if I was a member function within the class to which I am a friend? In other words, can I get at the protected and public members of the base class which is privately inherited from since I am a friend?

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • 5
    Seeing as you've gone to the trouble to write up example code, have you tried *compiling it*? This sort of answer would very quickly come to light in the warnings/lack-of. – ssube Mar 26 '12 at 19:51
  • 2
    @peachykeen: What compilers accept and what the standard says are often different things. Also, there could, in theory, be subtleties that the sample code doesn't capture. – Adrian McCarthy Mar 26 '12 at 20:13
  • @AdrianMcCarthy That is true. However, many compilers will warn when non-standard features are used, and if it's against the standard and the compiler's implementation, you'll get a short and sweet answer. While not foolproof, it can't hurt to try. – ssube Mar 27 '12 at 13:43

3 Answers3

7

Combining the answers of David Rodríguez - dribeas and Luchian Grigore:

Yes, the example in the question works, however, as David points out, the protected members are not accessible directly through the base class. You only get access to the protected members when accessed through Derived, you do not have access to the same members when accessed through Base.

In other words, the protected members of base are treated as if they were private members of derived and thus friends can see them, but, if you cast to the base class, there is no friend relationship, and thus the protected members are no longer accessible.

Here is an example that clarifies the difference:

class MyFriend {
  Derived _derived;

  void test() {
    bool thisWorks = _derived.pub;
    bool thisAlsoWorks = _derived.prot;

    Base &castToBase = _derived;

    bool onlyPublicAccessNow = castToBase.pub;
    // Compiler error on next expression only.
    // test.cpp:13: error: `bool Base::prot' is protected
    bool noAccessToProtected = castToBase.prot;
  }
};
WilliamKF
  • 41,123
  • 68
  • 193
  • 295
2

The friend declaration will make MyFriend have access to the inheritance relationship (that is private for the rest of the world) but will not grant it access to the protected members of the base, only to the public interface.

void MyFriend::test() {
   Derived d;
   Base & b = d;          // Allowed, MyFriend has access to the relationship
   b.prot = false;        // Not allowed, it does not have access to the base
}
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
1

Yes, because Base's members are also Derived's members (since they are not private in Base).

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625