Разрешить классу C ++ доступ к некоторому «внутреннему» члену другого класса, но не к частному? - PullRequest
3 голосов
/ 06 октября 2011

При кодировании классов, которые тесно связаны функционально, но где вы хотите простой интерфейс с остальным миром, было бы замечательно, если бы я мог сделать что-то вроде этого:

class log
{
private:
  log_context& cont;
public:
  create_log_section(std::string name)
  {
    cont.create_log_section(name);// this is fine! It's "internal"
    cont.this_is_private();       // doesn't compile. Don't want anyone touching my privates!
  }
};

class log_context
{
internal:
  void create_log_section(std::string name);
private:
  void this_is_private();
internal friend log;             // Wow, possible?
}

Теперь этопозволит журналу получить доступ к соответствующим частям контекста, но не к частным.Остальная часть программы должна использовать log для добавления любого контекста.Кроме того, он может передавать строго типизированный log_contexts между журналами без дополнительной мощности.Я понимаю, что это конкретное решение невозможно, но каковы некоторые общие, если таковые имеются?

Ответы [ 3 ]

7 голосов
/ 06 октября 2011

Вы можете использовать внутренний класс, чтобы сделать это

class log_context
{
    class internal
    {
        friend log;

        static void create_log_section( log_context & context, std::string name)
        {
            context.create_log_section( name );
        } 
    }

    private:
        void create_log_section(std::string name);
        void this_is_private();
}

class log
{
    private:

    log_context& cont;

    public:

    void create_log_section(std::string name)
    {
        log_context::internal::create_log_section( cont, name );// this is fine! It's "internal"
    }
};

Как внутренний, так и только частные статические функции, только его друзья могут получить к нему доступ

4 голосов
/ 06 октября 2011

Дружба не пересекает границы наследства. Если бы log_context должен был унаследовать некоторые log_context_base, а this_is_private был бы частью log_context_base, то log_context, являющийся другом log, не позволил бы log получить доступ к this_is_private.

class log_context_base
{
protected:
  void this_is_private();
}

class log_context : protected log_context_base
{
internal:
  void create_log_section(std::string name);
  friend log; 
}

Обратите внимание, что здесь я использовал защищенное наследование, потому что не ожидаю, что log_context будет доступен с помощью log_context_base*.

Таким образом, вы получите то, что хотите, без добавления нового ключевого слова к языку;)

0 голосов
/ 06 октября 2011

Общее решение - сделать друга full и, поскольку он находится под вашим контролем, просто убедитесь, что он касается только того, к чему он должен прикасаться.

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

class Key { friend class log; Key() {} ~Key() };

class log_context {
public:
  void create_log_section(std::string name, Key const&);
};

Только друг Key может создать его экземпляр, и поэтому только они (или те, кому они передают ссылку на ключ) могут получить доступ к «ограниченному» методу.

Я скорее поклонник этого метода для документирования ограниченного доступа.

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