Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a friend see base classes?

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?

like image 508
WilliamKF Avatar asked Mar 26 '12 19:03

WilliamKF


3 Answers

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;
  }
};
like image 145
WilliamKF Avatar answered Oct 11 '22 06:10

WilliamKF


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
}
like image 2
David Rodríguez - dribeas Avatar answered Oct 11 '22 06:10

David Rodríguez - dribeas


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

like image 1
Luchian Grigore Avatar answered Oct 11 '22 05:10

Luchian Grigore