На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Друзья класса , где вы?
    class T1{
    private:
    C1 *pC1;
    C2 *pC2;
    };
    class T2{
    private
    C3 *pC3;
    };

    Есть объекты
    T1 m1;
    T2 m2;

    Как из объекта m2 получить доступ к полю pC2 объекта m1?
    1. При этом любой другой класс не должен иметь доступа к полю pC2!
    2. При этом класс C2 должен иметь доступ только к pC2, поле pC1 должно оставаться для него недоступным.

    Хочу сделать что-то типа друга класса. Возожно ли это?
    Но вариант
    class T1{
    private:
    friend T2;
    C1 *pC1;
    C2 *pC2;
    };

    не проходит, ибо не выполняется условие 2.

    Как выполнить поставленную задачу?
      ExpandedWrap disabled
         
        class T0 {
         protected:
          C1 *pC1;
        };
         
        class T1: private T0 {
         private:
          friend class T2;
          C2 *pC2;
        };
        Не понимаю, что это даёт?

        pC1 станет protected для T1, а поскольку класс T2 станет другом для Т1, то и к рС1 он тоже будет иметь доступ.

        Или я не прав?

        Прошу приводить код с коммантариями

        Добавлено в :
        Да нет, не склероз. Просто раздел "Билдер" многие КЛАССНЫЕ программеры из раздела "Visual C" порсто не посещают. Вот потому я спрашиваю здесь
          Да такой пример действительно работать не будет. Забыл я его проверить.
          Придётся так:
          ExpandedWrap disabled
             
            class T0 {
             private:
              friend class T1;
              class C1 *pC1;
            };
             
            class T1: public T0 {
             private:
              friend class T2;
              class C2 *pC2;
            };

          Коментировать тут нечего доступ к pC1 имеет только T1, а разрешение на доступ к pC2 для T2 на pC1 не распространяется.
          Сообщение отредактировано: Flip -
            Да это решение... намученное правда...

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

            Спасибо. А ещё идеи есть? Например без использования дополнительного класса?

            З.Ы. 2Lucifer, видишь? Здесь есть более находчивые люди.
              ExpandedWrap disabled
                 
                class T1 {
                 private:
                  friend class FARSH;
                  class C2 *pC2;
                  class C1 *pC1;
                };
                 
                class FARSH {
                 private:
                  friend class T2;
                  static C2 * GetpC2(T1& t1) { return t1.pC2; }
                };
                 
                class T2 {
                  T1 t;
                 public:
                  T2() { C2 *pC2=FARSH::GetpC2(t); }
                };

              ExpandedWrap disabled
                 
                class T2 {
                 public:
                  T2(class T1& t) { class C2 *pC2=GetpC2(t); }
                  class C2 * GetpC2(T1& t1);
                };
                 
                class T1 {
                 private:
                  friend C2* T2::GetpC2(T1&);
                  class C2 *pC2;
                  class C1 *pC1;
                };
                 
                C2 * T2::GetpC2(T1& t1) {
                  return t1.pC2; // Но тут при желании можно обратиться к pC1!
                }
                2Flip - извращенец (в хорошем смысле)
                  Можно конечно придумать ещё несколько извратов на данную тему, по разному наследовать промежуточный класс в том числе и от T2 есть варианты, отработать использование protected, скрыть дополнительные функции с помощью define или template. Но сделать, как мне кажется, это красиво ну никак не выйдет.
                    M
                    Тopic moved here from Visual C++ / MFC / WTL / WinAPI
                      Цитата
                      Budda, 18.02.04, 11:26
                      Нужно чё-нить простое, но крутое!

                      :D
                        Можно замутить еще такой вариант. Предполагаем, что регулированием доступа занимается класс C1:
                        ExpandedWrap disabled
                           
                          class C1
                          {
                          public:
                              C1() {;}
                           
                          private:
                              // Объявляем класс, предоставляющий доступ
                              class BaseAccessor
                              {
                              public:
                                  BaseAccessor(C1* parent) : m_Parent(parent) {;}
                                  int GetC1() {return m_Parent->m_C1;}
                                  int GetC2() {return m_Parent->m_C2;}
                              private:
                                  C1* m_Parent;
                              };
                           
                              // Объявлеяем общий шаблон. Он будет использован для "остальных" классов
                              template<class T> class Accessor_t
                              {
                                  Accessor_t(C1* parent) {;};
                              };
                           
                              // Объявляем специализацию, которая открывает доступ конкретному классу
                              template<> class Accessor_t<C2*> : public BaseAccessor
                              {
                              public:
                                  Accessor_t(C1* parent) : BaseAccessor(parent) {;}
                              };
                           
                              friend class C1::BaseAccessor;
                           
                              int m_C1;
                              int m_C2;
                           
                          public:    
                              // Метод, возвращающий объект, через который будем получать доступ.
                              template<class T> Accessor_t<T*> GetAccess(T* obj)
                              {
                                  return Accessor_t<T*>(this);
                              }
                           
                          };
                           
                          class C2
                          {
                          public:
                              void Foo(C1* ptr);
                          };
                           
                           
                          void C2::Foo(C1* ptr)
                          {
                              ptr->GetAccess(this).GetC1();
                              ptr->GetAccess(this).GetC2();
                          }
                           
                          class C3
                          {
                          public:
                              void Foo(C1* ptr);
                          };
                           
                          void C3::Foo(C1* ptr)
                          {
                              //ptr->GetAccess(this).GetC1();
                              //ptr->GetAccess(this).GetC2();
                          }


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

                            ExpandedWrap disabled
                               
                              // Объявлеяем общий шаблон. Он будет использован для "остальных" классов
                               template<class T> class Accessor_t
                               {
                                Accessor_t(C1* parent) {;};
                               };
                               
                               // Объявляем специализацию, которая открывает доступ конкретному классу
                               template<> class Accessor_t<C2*> : public BaseAccessor
                               {
                               public:
                                Accessor_t(C1* parent) : BaseAccessor(parent) {;}
                               };
                              В С++ существует такая вещь - специализация шаблонов. Используется тогда, когда для конкретного типа шаблон должен вести себя особым образом. В приведенном примере у нас получается следующее. Общая специализация:
                              Цитата
                              Budda, 18.02.04, 16:46
                              template<class T> class Accessor_t
                              {
                              Accessor_t(C1* parent) {;};
                              };

                              Не содержит никаких методов доступа. Таким образом, когда мы будем инстанцировать этот шаблон - ни к какому методу мы обратиться не сможем (по причине их отсутствия).
                              Теперь делаем взмах руками над клавиатурой и...
                              Цитата
                              Budda, 18.02.04, 16:46
                              template<> class Accessor_t<C2*> : public BaseAccessor
                              {
                              public:
                              Accessor_t(C1* parent) : BaseAccessor(parent) {;}
                              };

                              Получаем, что если мы будем инстанцировать шаблон Accessor_t для типа C2*, то получим доступ к методам, объявленным в классе BaseAccessors. Т. е. объекты
                              Accessor_t<C2*> c2_accessor();
                              и
                              Accessor_t<C3*> c3_accessor();
                              будут вести себя по-разному и будут содержать разные методы.
                              Теперь мы еще немножко напрягаем компилятор, и делаем так, что он сам выбирает для нас нужную специализацию:
                              ExpandedWrap disabled
                                 
                                 // Метод, возвращающий объект, через который будем получать доступ.
                                 template<class T> Accessor_t<T*> GetAccess(T* obj)
                                 {
                                  return Accessor_t<T*>(this);
                                 }

                              используя факт того, что шаблонные методы могут инстанцироваться неявно. В итоге мы можем использовать все это описанным мною способом:
                              ExpandedWrap disabled
                                 
                                void C2::Foo(C1* ptr)
                                {
                                 ptr->GetAccess(this).GetC1();
                                 ptr->GetAccess(this).GetC2();
                                }

                              При этом доступом управляет сам класс C1, и на этапе компиляции мы получаем жесткий контроль - классы, которым "не положено" доступа не получат.
                              Сообщение отредактировано: Flex_Ferrum -
                                Эх нужно тестить, абстрактно догнать не могу.... :(
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0386 ]   [ 16 queries used ]   [ Generated: 15.05.24, 04:06 GMT ]