Сохранение части открытого вложенного класса видимым только для вложенного класса - PullRequest
3 голосов
/ 13 января 2011

У меня есть вложенный класс в c ++, который должен быть публичным. Но мне нужны некоторые из его методов, видимых для внешнего мира, а остальные видны только для класса вложенности. То есть:

class set {
public:
    class iterator {
        innerMethod();
    public:
        outerMethod();
    }
}

Я хочу иметь возможность написать метод для набора, который использует innerMethod (). Если я сделаю это публичным, я смогу получить к нему доступ и извне, чего я определенно не хочу. Есть ли способ сделать это, не используя «набор классов друзей»?

Заранее спасибо!

Ответы [ 5 ]

2 голосов
/ 13 января 2011

НЕТ ХОРОШЕГО СПОСОБА сделать это, не используя ключевое слово friend.

В комментарии вы сказали:

В классе программирования, который я сейчас использую, используяГоворят, что «друг» опрометчив и в большинстве случаев считается «плохим программированием», если на самом деле другого пути нет.Поэтому я стараюсь избегать этого в максимально возможной степени.

friend нарушает инкапсуляцию, возможно, именно поэтому ваш классный учитель сказал, что это плохое программирование. Но функции-члены тоже нарушают инкапсуляцию, тогда зачем вы их используете?Почему бы не избежать их тоже?friend нарушает инкапсуляцию так же, как и функции-члены; , поэтому, если вам удобно использовать функции-члены , когда они необходимы , тогда вам должно быть удобно использовать friend также когда они необходимы. Оба существуют в C ++ по определенной причине!

class set {
public:
 class iterator 
 {
  friend class set; //<---- this gives your class set to access to inner methods!

  void innerMethod(){}
 public:
  void outerMethod(){}
 };
 iterator it;

 void fun()
 {
  it.innerMethod();
  it.outerMethod();
 }
};

См. Это: Как функции, не являющиеся членами, улучшают инкапсуляцию

1 голос
/ 13 января 2011

Да, есть.

Я уже некоторое время пытаюсь защищать метод, основная идея в том, чтобы использовать класс Key.

Хотя это на самом деле не удаляет использование friend, оно сокращает набор открытых деталей реализации.

class set;

// 1. Define the Key class
class set_key: noncopyable { friend class set; set_key() {} ~set_key() {} };

class set
{

  // 2. Define the iterator
  class iterator
  {
  public:
    void public_method();

    void restricted_method(set_key&);

  }; // class iterator

}; // class set

Теперь restricted_method является общедоступным, поэтому set не требуется особый доступ к iterator. Однако его использование разрешено только тем, кто способен передать экземпляр set_key ... и, как правило, только set может создать такой объект.

Обратите внимание, что set может фактически передать объект set_key кому-то другому, кому он доверяет. Это ключ в традиционном смысле: если вы дадите кому-то ключ от своей квартиры, он может передать его другому человеку. Однако из-за семантики класса ключей (не копируемого, только set может создать и уничтожить его), это обычно ограничено продолжительностью области действия объекта key.

Обратите внимание, что злой хак всегда возможен, а именно *((set_key*)0). Эта схема защищает от Мерфи, а не Макиавелли (в любом случае это невозможно в C ++).

1 голос
/ 13 января 2011

Попробуйте спросить: есть ли способ добавить 2 числа без их добавления?Извините, если я груб, но класс друга именно для этого ...

1 голос
/ 13 января 2011

Нет, я не думаю, что есть другие нехакерские методы, кроме использования директивы friend.

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

0 голосов
/ 13 января 2011

Вы можете сделать что-то вроде этого:

набор классов

{

public:
    class iterator
    {
        protected:
            iterator(){};
            virtual ~iterator(){};

        public:
            //outer world methods...
    };

private:
    class privateIterator : public iterator
    {
        public:
            privateIterator(){};
            ~privateIterator(){}

        //inner methods;
    };

public:
    iterator* CreateIterator()
    {
        return new privateIterator();//this is used to be sure that you only create private iterator instances
    }

};

Я не знаю, правильный ли это ответ, но теперь он использует работу с ключом друга и скрывает некоторые методы. Единственная проблема заключается в том, что вы не можете объявить privateIterator, и вы всегда должны использовать CreateIterator для создания экземпляра ...

...