На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: JoeUser, 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;
    }
Мои программные ништякиhttp://majestio.info
Цитата mishapk @
Есть два класса работающие вместе общими глобальными переменными.

Надо глобальные переменные обернуть классом.
Сделать их "public" и "static".
Таким образом, любой экземпляр такого класса станет
объектом доступа к "глобальным" переменным.
Подпись была выключена в связи с наложенным заземлением.
Ну да, в том числе и для этого придумали синглтоны.
Мои программные ништякиhttp://majestio.info
Цитата 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;
    }
Мои программные ништякиhttp://majestio.info
Цитата JoeUser @
Цитата ЫукпШ @
Экземпляров класса может быть любое количество, в этом
и удобство.

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

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

В моей реализации переменные получат гарантированно-правильную инициализацию (и освобождение) ресурсов до использования - методы Init и Cleanup. В твоем случае нужно заботиться в предметном коде о недопущении использования до инициализации этих самых бывших "глобальных" переменных нужными значениями, а не полученными по-умолчанию. ИМХО, это аргумент.
Мои программные ништякиhttp://majestio.info
Цитата 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, или лучше вообще уйти от указателей и возвращать ссылку на статический член класса(Синглтон Майерса.).
А то у тебя код для двух статический переменных неоправданно навороченный.

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

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

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

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

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


Рейтинг@Mail.ru
[ Script Execution time: 0,1595 ]   [ 20 queries used ]   [ Generated: 25.09.18, 19:40 GMT ]