На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Инкапсуляция глобальных переменных
    Добрый день
    Есть два класса работающие вместе общими глобальными переменными.
    Хочу объединить все вместе в отдельный класс в том числе и переменные. Возникла проблема подклассы не видят у себя внутри этих переменные.

    Пример.
    До:
    int a,b,c,d; - глобальные переменные
    class Tx; - использует глобальные переменные
    class Ty; - использует глобальные переменные
    После:
    ExpandedWrap disabled
      My class
      {
       private:
         int a,b,c,d;
       public:
        Tx x;
        Ty y;
      }


    Какие будут идеи?
    Сообщение отредактировано: JoeUser -
      Цитата mishapk @
      Какие будут идеи?

      Не видят, потому что они у тебя private. Сделай protected.
      И, эти глобальные переменные разве не должны быть static?
        Не видят так как подклассы реализуются за пределами класса и они их просто не видят.
        Сделал подклассы вложенными, тоже не видят. В Java это вроде возможно а в С++ нет.
        Остается только через указатели в конструкторе подклассов передавать в виде структуры. Я так думаю.
          Некрасивый вариант:

          ExpandedWrap disabled
            #include <iostream>
            using namespace std;
             
            class Tx;
            class Ty;
             
            class Config {
              private:  
                int a = 2, b = 3;
                friend Tx;  
                friend Ty;
            };
             
            class Tx {
              public:  
                int GetA(Config &r) { return r.a; }
            };
             
            class Ty {
              public:  
                int GetB(Config &r) { return r.b*2; }
            };
             
            class Result {
              public:
                Config c;
                Tx x;
                Ty y;
            };
             
            int main() {
              Result R;
              cout << R.x.GetA(R.c) << endl;
              cout << R.y.GetB(R.c) << endl;
              return 0;
            }
            Цитата mishapk @
            Есть два класса работающие вместе общими глобальными переменными.

            Надо глобальные переменные обернуть классом.
            Сделать их "public" и "static".
            Таким образом, любой экземпляр такого класса станет
            объектом доступа к "глобальным" переменным.
              Ну да, в том числе и для этого придумали синглтоны.
                Цитата JoeUser @
                Ну да, в том числе и для этого придумали синглтоны.

                Нет, этого не нужно в данном случае.
                Экземпляров класса может быть любое количество, в этом
                и удобство.
                Экземпляр такого класса - это как-бы окошко многоквартирного
                дома. Каждое из которого выходит на один и тот же двор, и из каждого
                можно наблюдать одну и ту же картину.
                И есть возможность кинуть бутылку в одно и то же место.
                А из той квартиры, где этого окошка нет - дворика не видно.
                  Цитата ЫукпШ @
                  Экземпляров класса может быть любое количество, в этом
                  и удобство.

                  А так неудобно? См Test1Class и Test2Class:

                  ExpandedWrap disabled
                    #include <iostream>
                    using namespace std;
                     
                    ////////////////////////////////////////////////////////////////////////////////////////
                     
                    template<typename T>
                    struct Holder {
                      Holder() {
                        std::cout << "Holder()::Holder()" << std::endl;
                        if (!Self)  Self = new T();
                        Self->Init();
                      }
                      ~Holder() {
                        if (Self) {
                          Self->Cleanup();
                          delete Self;
                          std::cout << "~Holder()::Holder()" << std::endl;
                        }
                      }
                      T* Self = nullptr;
                    };
                     
                    ////////////////////////////////////////////////////////////////////////////////////////
                     
                    template <typename T>
                    class Singleton {
                      public:
                        static T* Instance() {
                          std::cout << "Singlton::Instance()" << std::endl;
                          static Holder<T> Dummy;
                          return Dummy.Self;
                        }
                      private:
                        Singleton() = delete;
                        Singleton(Singleton const&) = delete;
                        Singleton& operator= (Singleton const&) = delete;
                        Singleton(Singleton const&&) = delete;
                        Singleton& operator= (Singleton const&&) = delete;
                    };
                     
                    class Global {
                      public:
                        int GetA() {
                          cout << "GetA" << endl;
                          return x-1;
                        }
                        int GetB() {
                          cout << "GetB" << endl;      
                          return x+1;
                        }
                        void Init() {};
                        void Cleanup() {};
                      private:
                        int x = 1;
                    };
                     
                    struct Test1Class {
                      void Print() {
                        cout << Singleton<Global>::Instance()->GetA() << endl;      
                      }
                    };
                     
                    struct Test2Class {
                      void Print() {
                        cout << Singleton<Global>::Instance()->GetB() << endl;      
                      }
                    };
                     
                     
                    int main() {
                      Test1Class T1;
                      Test2Class T2;
                      T1.Print();
                      T2.Print();
                      return 0;
                    }
                    Цитата JoeUser @
                    Цитата ЫукпШ @
                    Экземпляров класса может быть любое количество, в этом
                    и удобство.

                    А так неудобно? См Test1Class и Test2Class:

                    Лично мне - нет.
                    Зачем мне дополнительные сущности для достижения той-же цели ?
                    Достаточно описать переменную как "static".
                      Цитата ЫукпШ @
                      Зачем мне дополнительные сущности для достижения той-же цели ?
                      Достаточно описать переменную как "static".

                      В моей реализации переменные получат гарантированно-правильную инициализацию (и освобождение) ресурсов до использования - методы Init и Cleanup. В твоем случае нужно заботиться в предметном коде о недопущении использования до инициализации этих самых бывших "глобальных" переменных нужными значениями, а не полученными по-умолчанию. ИМХО, это аргумент.
                        Цитата JoeUser @

                        ExpandedWrap disabled
                          private:
                              Singleton() = delete;
                              Singleton(Singleton const&) = delete;
                              Singleton& operator= (Singleton const&) = delete;
                              Singleton(Singleton const&&) = delete;
                              Singleton& operator= (Singleton const&&) = delete;

                        Их нужно в секцию public перенести. Не по феншую, когда удаленные мемберы в закрытой секции. В противном случае ты можешь получить невнятную ошибку компиляции, и сидеть гадать почему так.

                        А вместо класса Holder думаю имеет смысл использовать shared_ptr, или лучше вообще уйти от указателей и возвращать ссылку на статический член класса(Синглтон Майерса.).
                        А то у тебя код для двух статический переменных неоправданно навороченный.

                        Добавлено
                        Цитата JoeUser @
                        ExpandedWrap disabled
                          class Global {
                            public:
                              int GetA() {
                                cout << "GetA" << endl;
                                return x-1;
                              }
                              int GetB() {
                                cout << "GetB" << endl;      
                                return x+1;
                              }
                              void Init() {};
                              void Cleanup() {};
                            private:
                              int x = 1;
                          };

                        А этот класс я бы вообще выкинул, в нем нет никакого смысла.
                          Цитата Wound @
                          Их нужно в секцию public перенести. Не по феншую, когда удаленные мемберы в закрытой секции. В противном случае ты можешь получить невнятную ошибку компиляции, и сидеть гадать почему так.

                          Возможно. Но лучше поэксперементировать и посмотреть мой вариант и твой.
                          Цитата Wound @
                          А вместо класса Holder думаю имеет смысл использовать shared_ptr, или лучше вообще уйти от указателей и возвращать ссылку на статический член класса(Синглтон Майерса.).
                          А то у тебя код для двух статический переменных неоправданно навороченный.

                          Давай твой вариант для коллекции :)
                            Цитата JoeUser @
                            Возможно. Но лучше поэксперементировать и посмотреть мой вариант и твой.

                            В смысле поэкспериментировать? Дело в том, что когда ты пишешь = delete, то компилятор выбрасывает этот член класса. И если вдруг ты его юзнул - тебе он так и скажет, такоой метод помечен как удаленный, так что вызывай другой.
                            А когда ты его делаешь закрытым, то вполне можешь выхватить ошибку аля: не могу вызвать такой метод, он находится в секции private.
                            Когда речь идет о небольшой логике - никаких проблем не будет. Но вдруг если будет что то понавороченее, например с какими нибудь итераторами внутри second/first или еще чего, которые нужно будет куда нибудь перенести или скопировать, то можешь потратить много времени, на выявление ошибок.

                            Цитата JoeUser @
                            Давай твой вариант для коллекции :)

                            Тебе какой именно? С Синглтоном? ну хорошо, щас что нибудь напишу.
                              Цитата Wound @
                              А этот класс я бы вообще выкинул, в нем нет никакого смысла.

                              Это класс из которого "фабрика синглтонов" class Singlеton, собственно, и делает синглтон :) В этом классе и хранятся заветные "глобальные" переменные. Низя это выкидывать.
                                А вот интересно, как этот механизм инициализации статических переменных реализуется внутри. Где-то видел в листинге такой вариант - компилятор создает скрытую "совсем-совсем статическую" переменную, которая обнуляется вместе с .bss, после чего при каждом входе в функцию проверяет ее на равенство нулю и, если она ноль, инициализирует явную статическую переменную.
                                Мое чувство прекрасного сильно страдает от того, что явная переменная фактически дублирует неявную и что все эти действия реально нужны только один раз при запуске программы, но продолжают выполняться и отжирать процессорное время и электричество в течении всего времени выполнения программы.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0460 ]   [ 17 queries used ]   [ Generated: 28.03.24, 08:38 GMT ]