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

    Пример.
    До:
    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, после чего при каждом входе в функцию проверяет ее на равенство нулю и, если она ноль, инициализирует явную статическую переменную.
                                Мое чувство прекрасного сильно страдает от того, что явная переменная фактически дублирует неявную и что все эти действия реально нужны только один раз при запуске программы, но продолжают выполняться и отжирать процессорное время и электричество в течении всего времени выполнения программы.
                                  Цитата Wound @
                                  В смысле поэкспериментировать? Дело в том, что когда ты пишешь = delete, то компилятор выбрасывает этот член класса. И если вдруг ты его юзнул - тебе он так и скажет, такоой метод помечен как удаленный, так что вызывай другой.
                                  А когда ты его делаешь закрытым, то вполне можешь выхватить ошибку аля: не могу вызвать такой метод, он находится в секции private.
                                  Когда речь идет о небольшой логике - никаких проблем не будет. Но вдруг если будет что то понавороченее, например с какими нибудь итераторами внутри second/first или еще чего, которые нужно будет куда нибудь перенести или скопировать, то можешь потратить много времени, на выявление ошибок.


                                  Проверил сообщения.

                                  Для public секции:

                                  ExpandedWrap disabled
                                    prog.cpp: In function ‘int main()’:
                                    prog.cpp:10:5: error: use of deleted function ‘A::A()’
                                       A a;
                                         ^
                                    prog.cpp:6:5: note: declared here
                                         A() = delete;
                                         ^


                                  Для private секции:

                                  ExpandedWrap disabled
                                    prog.cpp: In function ‘int main()’:
                                    prog.cpp:10:5: error: ‘A::A()’ is private within this context
                                       A a;
                                         ^
                                    prog.cpp:6:5: note: declared private here
                                         A() = delete;
                                         ^


                                  Может ты и прав. Но пока я существенного не замечаю. Может потом... :whistle:

                                  Добавлено
                                  Цитата Wound @
                                  А вместо класса Holder думаю имеет смысл использовать shared_ptr,

                                  Класс Holder обеспечивает автоматическую инициализацию после создания экземпляра класса, и автоматическую очистку перед разрушением экземпляра класса. Это некое подобие функционала из Дэлфи :lol: (линк).
                                    Ну вот так наверное как то:
                                    ExpandedWrap disabled
                                      template<typename T>
                                      struct Singleton
                                      {
                                      private:
                                         Singleton() = default;
                                         ~Singleton() = default;
                                       
                                      public:
                                         Singleton(const Singleton&) = delete;
                                         Singleton& operator= (const Singleton&) = delete;
                                         Singleton(Singleton&&) = delete;
                                         Singleton& operator= (Singleton&&) = delete;
                                       
                                         static Singleton& Instance()
                                         {
                                            static Singleton<T> instance;
                                            return instance;
                                         }
                                       
                                         T Value() const
                                         {
                                            return Singleton<T>::Instance().m_value;
                                         }
                                       
                                         T& Value()
                                         {
                                            return Singleton<T>::Instance().m_value;
                                         }
                                       
                                       
                                      private:
                                         T m_value;
                                      };
                                       
                                      class A
                                      {
                                      public:
                                         void print()
                                         {
                                            std::cout << "A" << std::endl;
                                         }
                                      };
                                       
                                      class B
                                      {
                                      public:
                                         void print()
                                         {
                                            std::cout << "B" << std::endl;
                                         }
                                      };
                                       
                                       
                                      int main()
                                      {
                                         Singleton<A>& instA = Singleton<A>::Instance();
                                         Singleton<B>& instB = Singleton<B>::Instance();
                                       
                                         instA.Value().print();
                                         instB.Value().print();
                                       
                                         std::cin.get();
                                         return 0;
                                      }

                                    Это если конкретно через синглтон.

                                    Добавлено
                                    Цитата JoeUser @
                                    Может ты и прав. Но пока я существенного не замечаю. Может потом... :whistle:

                                    Ну ты на всех компиляторах проверил? А то например в 2017 студии пишет:
                                    ExpandedWrap disabled
                                      1>e:\develop\main.cpp(178): error C2248: 'C::C': cannot access private member declared in class 'C'
                                      1>e:\develop\main.cpp(172): note: see declaration of 'C::C'
                                      1>e:\develop\main.cpp(169): note: see declaration of 'C'

                                    Вот для вызова конструктора для такого класса:
                                    ExpandedWrap disabled
                                      class C
                                      {
                                      private:
                                         C() = delete;
                                      };

                                    В других компиляторах может быть иначе. Но я не вижу вообще никакого здавого смысла делать приватными удаляемые члены. Профита вообще 0. А вот если привыкнуть делать их открытыми, то профита куда больше.


                                    Цитата JoeUser @
                                    Класс Holder обеспечивает автоматическую инициализацию после создания экземпляра класса, и автоматическую очистку перед разрушением экземпляра класса. Это некое подобие функционала из Дэлфи :lol: (линк).

                                    Ничего он там не обеспечивает. Он накладывает ограничения на используемый класс. Вообще в С++ все эти действия делаеются в конструкторе/деструкторе. А для умных указателей shared_/unique/weak можно передать функцию deleter, если тебе нужно как то по особому очистить ресурс.
                                      Цитата Wound @
                                      Это если конкретно через синглтон.

                                      Вариант рабочий, но ИМХО, по ТЗ - не то. Топикстартеру нужно все глобальные переменные инкапсулировать в один класс, и потом дать к ним доступ из других классов.

                                      По твоему примеру это - в классах A и В должен быть доступ к таким переменным. А там пока только печать константной строки.
                                        Цитата Wound @
                                        Ничего он там не обеспечивает.

                                        Ну не тупи :lol:

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


                                        Умным указателям, как я понял, можно передать ТОЛЬКО "удалитель".

                                        Добавлено
                                        Киля, чтобы было понятно - напомню откуда "ноги растут" в моем коде. В С++ в конструкторе нельзя вызывать виртуальные функции. Таким образом только деструктор может быть виртуальным. Мой код обеспечивает функционал "виртуального конструктора". Как-то так.

                                        Добавлено
                                        Цитата Wound @
                                        Ну ты на всех компиляторах проверил? А то например в 2017 студии пишет:

                                        Если честно, я еще ни одной программы не скомпилировал в студии. Потому, что ее у меня нет. Хватает GCC и clang.
                                        Кстати, вот что пишет clang для ПРИВАТНОЙ секции:

                                        ExpandedWrap disabled
                                          prog.cc:10:5: error: call to deleted constructor of 'A'
                                            A a;
                                              ^
                                          prog.cc:6:5: note: 'A' has been explicitly marked deleted here
                                              A() = delete;
                                              ^
                                          1 error generated.

                                        Выкинь студию! :lol:
                                          Цитата JoeUser @
                                          Ну не тупи :lol:

                                          Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я.


                                          Цитата JoeUser @
                                          Топикстартеру нужно все глобальные переменные инкапсулировать в один класс, и потом дать к ним доступ из других классов.

                                          И в чем проблема? Получай на здоровье, например так:
                                          ExpandedWrap disabled
                                            template<typename T>
                                            struct Singleton
                                            {
                                            private:
                                               Singleton() = default;
                                               ~Singleton() = default;
                                             
                                            public:
                                               Singleton(const Singleton&) = delete;
                                               Singleton& operator= (const Singleton&) = delete;
                                               Singleton(Singleton&&) = delete;
                                               Singleton& operator= (Singleton&&) = delete;
                                             
                                               static Singleton& Instance()
                                               {
                                                  static Singleton<T> instance;
                                                  return instance;
                                               }
                                             
                                               T Value() const
                                               {
                                                  return Singleton<T>::Instance().m_value;
                                               }
                                             
                                               T& Value()
                                               {
                                                  return Singleton<T>::Instance().m_value;
                                               }
                                             
                                             
                                            private:
                                               T m_value;
                                            };
                                             
                                            class A
                                            {
                                            public:
                                               void print()
                                               {
                                                  std::cout << "A: " << a << std::endl;
                                               }
                                             
                                               int a;
                                             
                                            };
                                             
                                            class B
                                            {
                                            public:
                                               void print()
                                               {
                                                  std::cout << "B: " << b << std::endl;
                                               }
                                               int b;
                                            };
                                             
                                            class C
                                            {
                                            public:
                                               void DoSomething()
                                               {
                                                  Singleton<A>& instA = Singleton<A>::Instance();
                                                  Singleton<B>& instB = Singleton<B>::Instance();
                                             
                                                  instA.Value().print();
                                                  instB.Value().print();
                                               }
                                              
                                            };
                                             
                                             
                                            int main()
                                            {
                                               Singleton<A>& instA = Singleton<A>::Instance();
                                               Singleton<B>& instB = Singleton<B>::Instance();
                                             
                                               instA.Value().a = 10;
                                               instB.Value().b = 20;
                                             
                                               instA.Value().print();
                                               instB.Value().print();
                                             
                                               std::cout << "-------C---------" << std::endl;
                                               C c;
                                               c.DoSomething();
                                             
                                               std::cin.get();
                                               return 0;
                                            }

                                          Это же синглентон, где хочешь там и вызывай его. У тебя гарантированно будет 1 экземпляр класса.
                                            Цитата Wound @
                                            Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я.

                                            Так это же специально и сделано было для этого! :lol:
                                              Цитата JoeUser @
                                              Умным указателям, как я понял, можно передать ТОЛЬКО "удалитель".

                                              Cоздатель, ВНЕЗАПНО, вызывается в момент конструирования указателя. Что целиком и полностью удовлетворяет идиоме RAII.

                                              Цитата JoeUser @
                                              Киля, чтобы было понятно - напомню откуда "ноги растут" в моем коде. В С++ в конструкторе нельзя вызывать виртуальные функции. Таким образом только деструктор может быть виртуальным. Мой код обеспечивает функционал "виртуального конструктора". Как-то так.

                                              Твой код накладывает ограничение на использование объектов разных типов. Что если мне нужно передать в твой Holder shared_ptr объект?

                                              Цитата JoeUser @
                                              Если честно, я еще ни одной программы не скомпилировал в студии. Потому, что ее у меня нет. Хватает GCC и clang.
                                              Кстати, вот что пишет clang для ПРИВАТНОЙ секции:

                                              Речь идет не о конкретно студии. Речь идет о хорошем стиле программирования. Писать удаленные методы в приватной секции не по феншую. Понимаешь?

                                              Добавлено
                                              Цитата JoeUser @
                                              Так это же специально и сделано было для этого! :lol:

                                              Зачем? Что бы постоянно городить обертки с пустыми Init и Cleanup? :jokingly:
                                              Сообщение отредактировано: Wound -
                                                Цитата Wound @
                                                И в чем проблема?

                                                Проблема в том, что эти переменные "а" и "b" должны хранится вне классов A и B.
                                                Ну прочти самое первое сообщение топикстартера :)
                                                  Цитата JoeUser @
                                                  Проблема в том, что эти переменные "а" и "b" должны хранится вне классов A и B.

                                                  Если ты еще не понял, то эти классы A и B и есть переменные, которые должны храниться вне этих классов. Попробуй выкинуть классы A и B. Если тебе нужны примитивные типы, создай структуру с нужным количеством членов и передай в синглтон. Все.
                                                  Сообщение отредактировано: Wound -
                                                    Цитата Wound @
                                                    Попробуй передать в свой Holder класс у которого нет Init и Cleanup, и ты поймешь о чем я.

                                                    Тут ничего страшного. В принципе можно еще шаблонами поиграться, чтобы на этапе компиляции вырезать вызовы. Лениво. Я уповаю на оптимизатор - их и так там не будет.

                                                    Цитата Wound @
                                                    Если ты еще не понял, то эти классы A и B и есть переменные, которые должны храниться вне этих классов. Попробуй выкинуть классы A и B. Если тебе нужны примитивные типы, создай структуру с нужным количеством типов и передай в синглтон. Все.

                                                    Просто сделай как просит топикстартер :)

                                                    Добавлено
                                                    Цитата Wound @
                                                    Cоздатель, ВНЕЗАПНО, вызывается в момент конструирования указателя.

                                                    Это не гибко. Я уже писал выше о невозможности сделать штатными средствами виртуальное конструирование.
                                                      Цитата JoeUser @
                                                      Тут ничего страшного. В принципе можно еще шаблонами поиграться, чтобы на этапе компиляции вырезать вызовы. Лениво. Я уповаю на оптимизатор - их и так там не будет.

                                                      А то, что тебе каждый раз придется делать обертки над типами, у которых нет этих методов - тебя не смущает? :huh:

                                                      Цитата JoeUser @
                                                      Просто сделай как просит топикстартер :)

                                                      Он просит чтоб было вот так, как я понял?
                                                      Цитата mishapk @
                                                      Пример.
                                                      До:
                                                      int a,b,c,d; - глобальные переменные
                                                      class Tx; - использует глобальные переменные
                                                      class Ty; - использует глобальные переменные
                                                      После:
                                                      ExpandedWrap disabled
                                                            Myclass
                                                            {
                                                             private:
                                                               int a,b,c,d;
                                                             public:
                                                              Tx x;
                                                              Ty y;
                                                            }

                                                      Какие будут идеи?

                                                      В такой постановке задачи, я сделаю соответствующие конструкторы у классов Tx/Ty И передам нужные переменные из класса MyClass

                                                      Добавлено
                                                      Цитата JoeUser @

                                                      Это не гибко. Я уже писал выше о невозможности сделать штатными средствами виртуальное конструирование.

                                                      Че это не гибко? :D А вызывать Init и Cleanup гибко? Конструктор/Деструктор вроде как раз их и заменяют, не? :unsure:
                                                        Цитата Wound @
                                                        В такой постановке задачи, я сделаю соответствующие конструкторы у классов Tx/Ty И передам нужные переменные из класса MyClass

                                                        По секрету: там будет 128 переменных! :lol:

                                                        Цитата Wound @
                                                        А то, что тебе каждый раз придется делать обертки над типами, у которых нет этих методов - тебя не смущает? :huh:

                                                        Можно предусмотреть базовый класс с пустыми вызовами, а в наследниках про эти функции забыть. Элементарно, Ватсон! :whistle:

                                                        Цитата Wound @
                                                        Конструктор/Деструктор вроде как раз их и заменяют, не?

                                                        Напоминаю! В конструкторе нельзя вызывать виртуальные функции. В моем коде - это решается.
                                                          Цитата JoeUser @
                                                          По секрету: там будет 128 переменных! :lol:

                                                          Тогда я объявлю массив и передам массив.
                                                          Если у меня куча классов, где эти переменные нужны, создам структуру, как я тебе писал выше и передам ее в синглтон. Структуру написать? Ок
                                                          ExpandedWrap disabled
                                                            struct MyType
                                                            {
                                                               int variable1;
                                                               shared_ptr<int> variable2;
                                                               MyObject variable3;
                                                               std::vector<some type> variable4;
                                                               ololo variable5;
                                                               int variable6;
                                                               int variable7;
                                                            ...
                                                            };
                                                            ..
                                                            auto& gVar = Singlenton<MyType>::Instance();
                                                             
                                                            gVar.Value().bla bla bla


                                                          Цитата JoeUser @
                                                          Можно предусмотреть базовый класс с пустыми вызовами, а в наследниках про эти функции забыть. Элементарно, Ватсон! :whistle:

                                                          Ну вот я захотел передать в твой холдер std::shared_ptr<A> че мне делать то? :huh:


                                                          Цитата JoeUser @
                                                          Напоминаю! В конструкторе нельзя вызывать виртуальные функции. В моем коде - это решается.

                                                          А зачем это нужно то? Я что сам не могу вызвать Init/Cleanup, если мне понадобиться?
                                                          А что если у меня Cleanup может генерировать исключение? Выходят я получу граблями в лоб из за твоего мега кода?
                                                            Цитата Wound @
                                                            Тогда я объявлю массив и передам массив.

                                                            Блин :lool: Ну так твой MyType и есть мой Global !!!

                                                            Цитата Wound @
                                                            Ну вот я захотел передать в твой холдер std::shared_ptr<A> че мне делать то? :huh:

                                                            Не пробовал, не знаю. Заверни его в структуру или класс и передай. Надо пробовать.

                                                            Цитата Wound @
                                                            А зачем это нужно то? Я что сам не могу вызвать Init/Cleanup, если мне понадобиться?

                                                            А можешь и забыть. А ненаследованный класс тебя заставит не забыть.

                                                            Цитата Wound @
                                                            А что если у меня Cleanup может генерировать исключение? Выходят я получу граблями в лоб из за твоего мега кода?
                                                            Подавляй. Считай - это полноценная часть деструктора. В деструкторе же ты не собираешься бросать исключения? Или собираешься? :)
                                                              Цитата JoeUser @
                                                              Блин :lool: Ну так твой MyType и есть мой Global !!!

                                                              Нет, у меня MyType - это структура это отдельный тип, который агрегирует в себе 7 переменных разных типов, и передается в синглентон. У тебя твой Holder может принять ровно 1 объект одного типа, и зачем то вызывает для него Init в конструкторе и Cleanup в деструкторе.
                                                              Моя структура чем то отдаленно похожа на твой класс Global, и то я не уверен в этом.


                                                              Цитата JoeUser @
                                                              Не пробовал, не знаю. Заверни его в структуру или класс и передай. Надо пробовать.

                                                              Так я тебе скажу - оно не скомпилируется. А потом, если допустим даже предположить, что я завернул свой shared_ptr в класс и определил там методы Init и Cleanup - то даже в этом случае твой код небезопасен в плане исключений, потому как не дай бог у меня внутри функции Init что то понасоздается, а потом вдруг произойдет исключение в ней же. Все, каюк утечка ресурсов обеспечена.

                                                              Цитата JoeUser @
                                                              А можешь и забыть. А ненаследованный класс тебя заставит не забыть.

                                                              Я так не пишу, соответственно и забывать мне нечего. Твой код не удовлетворяет RAII, соответственно он не безопасный.

                                                              Цитата JoeUser @
                                                              Подавляй. Считай - это полноценная часть деструктора. В деструкторе же ты не собираешься бросать исключения? Или собираешься? :)

                                                              Дело в том, что деструктор - это часть языковой конструкции класса, поведение которой четко оговорено, и я знаю что от него ожидать или нет. А твой метод Cleanup - ни к селу ни к городу.

                                                              Добавлено
                                                              Во, попробовал поиграться с твоим кодом, выхватил по щам в рантайме:
                                                              https://ideone.com/VP5Y8i
                                                              ExpandedWrap disabled
                                                                #include <iostream>
                                                                #include <memory>
                                                                 
                                                                 
                                                                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;
                                                                };
                                                                 
                                                                class SomeClass
                                                                {
                                                                public:
                                                                   void Init(){}
                                                                   void Cleanup() {}
                                                                   int member;
                                                                };
                                                                 
                                                                ////////////////////////////////////////////////////////////////////////////////////////
                                                                 
                                                                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;
                                                                };
                                                                 
                                                                int main()
                                                                {
                                                                   {
                                                                      auto pInst = Singleton<SomeClass>::Instance();
                                                                      pInst->member = 10;
                                                                      std::cout << pInst->member << std::endl;
                                                                      std::unique_ptr<SomeClass> pObj(pInst);
                                                                   }
                                                                   auto pInst = Singleton<SomeClass>::Instance();
                                                                   pInst->member = 20;
                                                                 
                                                                   return 0;
                                                                }

                                                              ExpandedWrap disabled
                                                                *** Error in `./prog': double free or corruption (fasttop): 0x0000557abbacbc30 ***
                                                                ======= Backtrace: =========
                                                                /lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x2ba3cbcb8bcb]
                                                                /lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x2ba3cbcbef96]
                                                                /lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x2ba3cbcbf78e]
                                                                ./prog(+0xe77)[0x557ab9b48e77]
                                                                /lib/x86_64-linux-gnu/libc.so.6(+0x35920)[0x2ba3cbc7d920]
                                                                /lib/x86_64-linux-gnu/libc.so.6(+0x3597a)[0x2ba3cbc7d97a]
                                                                /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf8)[0x2ba3cbc682b8]
                                                                ./prog(+0xd4a)[0x557ab9b48d4a]
                                                                ======= Memory map: ========
                                                                2ba3caf68000-2ba3caf8b000 r-xp 00000000 fd:00 2840974                    /lib/x86_64-linux-gnu/ld-2.24.so
                                                                2ba3caf8b000-2ba3caf8f000 rw-p 00000000 00:00 0
                                                                2ba3caf98000-2ba3caf9d000 rw-p 00000000 00:00 0
                                                                2ba3cb18b000-2ba3cb18c000 r--p 00023000 fd:00 2840974                    /lib/x86_64-linux-gnu/ld-2.24.so
                                                                2ba3cb18c000-2ba3cb18d000 rw-p 00024000 fd:00 2840974                    /lib/x86_64-linux-gnu/ld-2.24.so
                                                                2ba3cb18d000-2ba3cb18e000 rw-p 00000000 00:00 0
                                                                2ba3cb18e000-2ba3cb300000 r-xp 00000000 fd:00 2967755                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
                                                                2ba3cb300000-2ba3cb500000 ---p 00172000 fd:00 2967755                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
                                                                2ba3cb500000-2ba3cb50a000 r--p 00172000 fd:00 2967755                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
                                                                2ba3cb50a000-2ba3cb50c000 rw-p 0017c000 fd:00 2967755                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
                                                                2ba3cb50c000-2ba3cb510000 rw-p 00000000 00:00 0
                                                                2ba3cb510000-2ba3cb613000 r-xp 00000000 fd:00 2841003                    /lib/x86_64-linux-gnu/libm-2.24.so
                                                                2ba3cb613000-2ba3cb812000 ---p 00103000 fd:00 2841003                    /lib/x86_64-linux-gnu/libm-2.24.so
                                                                2ba3cb812000-2ba3cb813000 r--p 00102000 fd:00 2841003                    /lib/x86_64-linux-gnu/libm-2.24.so
                                                                2ba3cb813000-2ba3cb814000 rw-p 00103000 fd:00 2841003                    /lib/x86_64-linux-gnu/libm-2.24.so
                                                                2ba3cb814000-2ba3cb82a000 r-xp 00000000 fd:00 2840941                    /lib/x86_64-linux-gnu/libgcc_s.so.1
                                                                2ba3cb82a000-2ba3cba29000 ---p 00016000 fd:00 2840941                    /lib/x86_64-linux-gnu/libgcc_s.so.1
                                                                2ba3cba29000-2ba3cba2a000 r--p 00015000 fd:00 2840941                    /lib/x86_64-linux-gnu/libgcc_s.so.1
                                                                2ba3cba2a000-2ba3cba2b000 rw-p 00016000 fd:00 2840941                    /lib/x86_64-linux-gnu/libgcc_s.so.1
                                                                2ba3cba2b000-2ba3cba43000 r-xp 00000000 fd:00 2840960                    /lib/x86_64-linux-gnu/libpthread-2.24.so
                                                                2ba3cba43000-2ba3cbc42000 ---p 00018000 fd:00 2840960                    /lib/x86_64-linux-gnu/libpthread-2.24.so
                                                                2ba3cbc42000-2ba3cbc43000 r--p 00017000 fd:00 2840960                    /lib/x86_64-linux-gnu/libpthread-2.24.so
                                                                2ba3cbc43000-2ba3cbc44000 rw-p 00018000 fd:00 2840960                    /lib/x86_64-linux-gnu/libpthread-2.24.so
                                                                2ba3cbc44000-2ba3cbc48000 rw-p 00000000 00:00 0
                                                                2ba3cbc48000-2ba3cbddd000 r-xp 00000000 fd:00 2841097                    /lib/x86_64-linux-gnu/libc-2.24.so
                                                                2ba3cbddd000-2ba3cbfdc000 ---p 00195000 fd:00 2841097                    /lib/x86_64-linux-gnu/libc-2.24.so
                                                                2ba3cbfdc000-2ba3cbfe0000 r--p 00194000 fd:00 2841097                    /lib/x86_64-linux-gnu/libc-2.24.so
                                                                2ba3cbfe0000-2ba3cbfe2000 rw-p 00198000 fd:00 2841097                    /lib/x86_64-linux-gnu/libc-2.24.so
                                                                2ba3cbfe2000-2ba3cbfe6000 rw-p 00000000 00:00 0
                                                                2ba3cc000000-2ba3cc021000 rw-p 00000000 00:00 0
                                                                2ba3cc021000-2ba3d0000000 ---p 00000000 00:00 0
                                                                557ab9b48000-557ab9b4a000 r-xp 00000000 fd:00 23353346                   /home/g1NiFf/prog
                                                                557ab9d49000-557ab9d4a000 r--p 00001000 fd:00 23353346                   /home/g1NiFf/prog
                                                                557ab9d4a000-557ab9d4b000 rw-p 00002000 fd:00 23353346                   /home/g1NiFf/prog
                                                                557abbab9000-557abbaeb000 rw-p 00000000 00:00 0                          [heap]
                                                                7fff4aec3000-7fff4aee4000 rw-p 00000000 00:00 0                          [stack]
                                                                7fff4afee000-7fff4aff0000 r-xp 00000000 00:00 0                          [vdso]
                                                                7fff4aff0000-7fff4aff2000 r--p 00000000 00:00 0                          [vvar]
                                                                ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


                                                              Это я еще не генерировал исключение в Init.
                                                                Цитата Wound @
                                                                метод Cleanup - ни к селу ни к городу.

                                                                A добавлю в описалово noexcept - только попробуй выбросить необработанное исключение :lol:

                                                                Цитата Wound @
                                                                Твой код не удовлетворяет RAII

                                                                В каком месте кода?
                                                                  Цитата JoeUser @
                                                                  A добавлю в описалово noexcept - только попробуй выбросить необработанное исключение :lol:

                                                                  В Init тоже добавишь?

                                                                  Цитата JoeUser @
                                                                  В каком месте кода?

                                                                  Везде. Вот например, лови:
                                                                  ExpandedWrap disabled
                                                                    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 SomeClass
                                                                    {
                                                                    public:
                                                                       void Init()
                                                                       {
                                                                          connect();
                                                                          initialize();
                                                                       }
                                                                     
                                                                       void Cleanup()
                                                                       {
                                                                          disconnect();
                                                                       }
                                                                     
                                                                       void connect()
                                                                       {
                                                                          std::cout << "connect" << std::endl;
                                                                       }
                                                                     
                                                                       void disconnect()
                                                                       {
                                                                          std::cout << "disconnect" << std::endl;
                                                                       }
                                                                     
                                                                       void initialize()
                                                                       {
                                                                          std::cout << "initialize" << std::endl;
                                                                          throw "Aaaaaaaaaaaaaaaaa";
                                                                       }
                                                                       int member;
                                                                    };
                                                                     
                                                                    int main()
                                                                    {
                                                                       {
                                                                          auto pInst = Singleton<SomeClass>::Instance();
                                                                          pInst->member = 10;
                                                                          std::cout << pInst->member << std::endl;
                                                                       }
                                                                       auto pInst = Singleton<SomeClass>::Instance();
                                                                       pInst->member = 20;
                                                                     
                                                                       return 0;
                                                                    }


                                                                  Добавлено
                                                                  Вот:
                                                                  https://ideone.com/8l75us
                                                                  Потерял ресурс, выхватил дедлок, не закрыл соединение, получил мемори лик...
                                                                  Сообщение отредактировано: Wound -
                                                                    Цитата Wound @
                                                                    Во, попробовал поиграться с твоим кодом, выхватил по щам в рантайме:

                                                                    Ваще ниче не понял в твоей задумке! Но это жесть ... Я бы еще разделил на нуль для надежности !!! :blink:

                                                                    Добавлено
                                                                    Цитата Wound @
                                                                    В Init тоже добавишь?

                                                                    Надо и в Инит добавлять 8-)
                                                                      Цитата JoeUser @
                                                                      Ваще ниче не понял в твоей задумке! Но это жесть ... Я бы еще разделил на нуль для надежности !!! :blink:

                                                                      Ну ты из синглтона возвратил указатель на класс, я же могу его передать куда нибудь дальше в функцию?
                                                                      Например, что мешает мне написать вот так:
                                                                      ExpandedWrap disabled
                                                                        void SomeFunction(std::unique_ptr<SomeClass>&& obj)
                                                                        {
                                                                         
                                                                        }
                                                                         
                                                                        int main()
                                                                        {
                                                                             std::unique_ptr<SomeClass> pObj(Singleton<SomeClass>::Instance());
                                                                             SomeFunction(std::move(pObj));
                                                                        }

                                                                      ?? И выхватить исключение?

                                                                      Цитата JoeUser @
                                                                      Надо и в Инит добавлять 8-)

                                                                      А зачем? В конструкторах что исключения плохо бросать? :huh: А если мне нужно кинуть в Init исключение? Что мне делать то?
                                                                        Ребят, вы в Холивары не хотите переехать? Бо как ТС спросил вас, как ему сложить три сущности, а вы втираете ему про алгебру Ли и разбираете разницы гомоморфизмов своих разных методов сложения.
                                                                          Ну можно и в холивары, я не против.
                                                                            Скрытый текст
                                                                            Цитата Qraizer @
                                                                            Ребят, вы в Холивары не хотите переехать?

                                                                            Цитата Wound @
                                                                            Ну можно и в холивары, я не против.

                                                                            Не, я пожалуй пойду выпью чаю и съем еще французских булочек 8-) Киля - победил.
                                                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                            0 пользователей:


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