Друг видит базовые классы?

Учитывая пример кода:

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;
  }
};

Дает ли мне дружба весь доступ, который я получил бы, как если бы я был функцией-членом в классе, для которого я друг? Другими словами, могу ли я получить доступ к защищенным и общедоступным членам базового класса, который унаследован в частном порядке, так как я друг?


person WilliamKF    schedule 26.03.2012    source источник
comment
Увидев, что вы приложили усилия, чтобы написать пример кода, пробовали ли вы его компилировать? Такой ответ очень быстро обнаружился бы в предупреждениях/отсутствии.   -  person ssube    schedule 26.03.2012
comment
@peachykeen: То, что принимают компиляторы, и то, что говорит стандарт, часто являются разными вещами. Кроме того, теоретически могут быть тонкости, которые не фиксирует пример кода.   -  person Adrian McCarthy    schedule 27.03.2012
comment
@AdrianMcCarthy Это правда. Однако многие компиляторы предупредят об использовании нестандартных функций, и если это противоречит стандарту и реализации компилятора, вы получите короткий и приятный ответ. Хотя это и не надежно, попробовать не помешает.   -  person ssube    schedule 27.03.2012


Ответы (3)


Объединяя ответы Давида Родригеса - дрибеаса и Лучиана Григоре:

Да, пример в вопросе работает, однако, как указывает Дэвид, защищенные члены недоступны напрямую через базовый класс. Вы получаете доступ только к защищенным членам при доступе через Derived, у вас нет доступа к тем же членам при доступе через Base.

Другими словами, защищенные члены базового класса обрабатываются так, как если бы они были частными членами производного класса, и, таким образом, друзья могут их видеть, но, если вы приводите к базовому классу, дружественных отношений не возникает, и, таким образом, защищенные члены больше не доступный.

Вот пример, поясняющий разницу:

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;
  }
};
person WilliamKF    schedule 27.03.2012

Объявление друга даст MyFriend доступ к отношениям наследования (то есть private для остального мира), но не предоставит ему доступ к защищенным членам базы, только к общедоступному интерфейсу.

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
}
person David Rodríguez - dribeas    schedule 26.03.2012

Да, потому что участники Base также являются участниками Derived (поскольку они не private в Base).

person Luchian Grigore    schedule 26.03.2012