LINUX.ORG.RU

Доступ к глобальным переменным


0

0

Я довольно долго использовал Delphi (наиболее неуравновешенных попрошу держать своё бесценное мнение по этому вопросу при себе) и теперь решил попробовать C/C++. Первый вопрос, который меня сильно озадачил, сводится к следующему. В Delphi более или менее крупные проекты у меня состояли из нескольких модулей (pas-файлов), причём один pas-файл я, как правило, выделял для глобальных переменных, доступ к которым был нужен нескольким модулям. В соответствующих модулях в interface или в implementation писалось "uses variables", и на этом проблема доступа к глобальным переменным полностью решалась. Вопрос. Как это реализуется в C/C++? Например, я в QtDesigner сделал приложение из main form и диалога. Обоим модулям (это файлы *.ui.h) нужен доступ к переменной X. Куда её поместить?

anonymous

Глобальные переменные - зло. Но, если уж очень хочется, делай так:

file1.cpp: int variable = 42;

file2.cpp: extern int variable; // и теперь её можно использовать // но сначала стоило бы прочитать умную книжку про C или С++ ( смотря на чем писать хочешь ) 

devinull ★★
()
Ответ на: комментарий от devinull

> Глобальные переменные - зло.

Ну зачем же так? Например, если многие модули моей программы используют как параметр при вычислениях текущий курс бакса, который каждые 5 минут опрашивается из интернета? Каждый модуль должен его опрашивать сам каждый раз и хранить у себя? А если один опросил чуть раньше, второй чуть позже, курс у них разный и в итоге бардак-с? Чем глобальная переменная хуже, чем делать функцию GetCurrentRate? Кода меньше и бинарник тоньше? В этом недостаток? :)

> Но, если уж очень хочется, делай так:

OK, спасибо.

anonymous
()
Ответ на: комментарий от anonymous

Ну в такой ситуации спасает singleton object, или класс со статическим private полем и статической же публичной функцией. Первое, наверное, правильнее - ибо меньше проблем будет когда тебе потребуется еще и курс евро.

hint: а что будет, если две функции отработают одна сразу перед, а другая сразу после выкачивания/обновления глобальной переменной? Не бардак? Опять же, не отслеживаются ситуации случайного изменения значение ('=' вместо '==', или передача по ссылке в модуль, думающий что это in-out параметр - такое тоже бывает).

anonymous
()

Глобальные переменные, которые не должны быть доступны из других модулей, нужно объявлять как static внутри *.c / *.cpp файлов.

bbk123 ★★★★★
()
Ответ на: комментарий от anonymous

> Ну в такой ситуации спасает singleton object, или класс со статическим private полем и статической же публичной функцией. Первое, наверное, правильнее - ибо меньше проблем будет когда тебе потребуется еще и курс евро.

Может быть. Но я не люблю усложнять без нужды.

> hint: а что будет, если две функции отработают одна сразу перед, а другая сразу после выкачивания/обновления глобальной переменной? Не бардак?

Если опрос осуществляет ОДИН модуль, то я могу этой ситуацией управлять и прогнозировать/предотвращать возможное изменение при нужде (выставлять глобальный флаг, блокирующий обновление, и пр.). Если же каждый делает всё сам, то ситуация становится сложноконтролируемой.

> Опять же, не отслеживаются ситуации случайного изменения значение ('=' вместо '==', или передача по ссылке в модуль, думающий что это in-out параметр - такое тоже бывает).

Да, это для меня, в связи с переходом с паскаля, весьма актуально ... Там-то как раз "=" - сравнение :(

anonymous
()
Ответ на: комментарий от anonymous

>Может быть. Но я не люблю усложнять без нужды.

ты не усложняешь - ты избавляешься от ошибкоопсных мест

Pi ★★★★★
()

Кстати, а есть ли вообще Qt 3 под windows? Просто у меня в линуксе стоит Qt 3.3.4, вот я в ней и барахтаюсь. А под win на сайте я нашёл только 4.x. А она мой проект читать не желает.

anonymous
()
Ответ на: комментарий от anonymous

> Может быть. Но я не люблю усложнять без нужды.

Совершенно ничего сложного нет.

> Если опрос осуществляет ОДИН модуль, то я могу этой ситуацией управлять и прогнозировать/предотвращать возможное изменение при нужде (выставлять глобальный флаг, блокирующий обновление, и пр.). Если же каждый делает всё сам, то ситуация становится сложноконтролируемой.

С т.з. C++ "модуль" - это класс. Паскальский модуль ничем не отличается от "полностью статического" класса (т.е. с приватным конструктором и только статическими публичными функциями) - разве что обращаться придется по полному имени, но это даже хорошо...

anonymous
()

> причём один pas-файл я, как правило, выделял для глобальных переменных, >доступ к которым был нужен нескольким модулям.

нужно создать .h файл с объявлением типа
extern int gVar; - аналог секции interface
и .cpp - аналог imlentation с
#include "file.h"

int gVar;

и когда нужен вместо users vars
пишешь
#include "file.h"

fghj ★★★★★
()

Ничего "сложного" или "криминального" с точки зрения алгоритма в глобальных переменных нету.

Но есть еще одна сторона: оптимизация.

Современные компиляторы все норовят сильно соптимизировать. И локальные переменные у них получается соптимизировать обычно получше, чем глобальные.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Может всё-таки стоит сначала почитать "Приёмы ОБъектно-ориентированного программирования" GoF? Qt3 есть под винду, но всячески советую Вам писать под qt4. Кстати говоря, Ваш проект коммерческий? Если да, то вы НЕ ИМЕЕТЕ право бесплатно пользовать Qt! Берите Gtk.

anonymous
()
Ответ на: комментарий от anonymous

>Чем глобальная переменная хуже, чем делать функцию GetCurrentRate? Кода меньше и бинарник тоньше? В этом недостаток? :)

А что ты будешь делать, если тебе вдруг понадобится работать с этой переменной из нескольких потоков одновременно? GetCurrentRate просто сделаешь thread-safe и нет проблем. Это я к уже вдобавок к уже сказанному.

devinull ★★
()
Ответ на: комментарий от anonymous

> Кстати говоря, Ваш проект коммерческий?

Как может быть коммерческим софт, который я пишу на фирме для внутреннего использования этой же фирмой? Я ж его никому продавать не собираюсь. Да он и не нужен никому, кроме этой фирмы - специфики больно много.

anonymous
()
Ответ на: комментарий от Die-Hard

>Ничего "сложного" или "криминального" с точки зрения алгоритма в глобальных переменных нету.

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

devinull ★★
()
Ответ на: комментарий от devinull

> А что ты будешь делать, если тебе вдруг понадобится работать с этой переменной из нескольких потоков одновременно? GetCurrentRate просто сделаешь thread-safe и нет проблем. Это я к уже вдобавок к уже сказанному.

А в чём проблема? В Delphi у меня не было траблов прочитать глобальную переменную из нескольких тредов. Изменяет её значение всегда только один тред. В C есть какие-то проблемы с этим?

anonymous
()
Ответ на: комментарий от bbk123

>Глобальные переменные, которые не должны быть доступны из других модулей, нужно объявлять как static внутри *.c / *.cpp файлов.

Внутри *.cpp им следует быть описанными внутри безымянного пространства имен, если уж на то пошло.

devinull ★★
()
Ответ на: комментарий от devinull

> А ты лицензию на qt прочитай, там про это как раз говорится.

Почитал. Там про сорцы и distribute. Дистрибутовать я буду фирме. Сорцы фирма получит тоже (правда, без меня они ей не особо и нужны). Где проблема?

anonymous
()
Ответ на: комментарий от anonymous

Delphi и С и даже Visual Basic тут абсолютно не причем. У тебя одна из простейших ситуаций. А что, если будет что-то посложнее?

int num_users = 0;

class A { public: A() { ++ num_users; if( num_users == 1 ) выделить_память_под_что_нибудь(); }

~A() { -- num_users; if( num_users == 0 ) вернуть_память_например(); } };

И что будет, если объекты будут создаваться и уничтожаться в несколько потоков? Либо segfault, либо memleaks, а уж потом segfault.

devinull ★★
()
Ответ на: комментарий от devinull

devinull :

> ...порядок инициализации конструирования глобальных объектов не определен стандартом и зависит от копмилятора и фаз луны ...

Если твой алгоритм зависит от порядка инициализации глобальных переменных, то ССЗБ.

А если все правильно, то ни малейших сюрпризов не будет.

Die-Hard ★★★★★
()
Ответ на: комментарий от devinull

> И что будет, если объекты будут создаваться и уничтожаться в несколько потоков? Либо segfault, либо memleaks, а уж потом segfault.

Ну да, в этом конкретном случае возможны траблы. Но это не отменяет глобальные переменные вообще: в более простых случаях они вполне применимы.

anonymous
()
Ответ на: комментарий от devinull

> Если я правильно понимаю, все-таки тебе нужна коммерческая лицензия.

Момент.

No. Software developed with the Qt Open Source Edition is always open source software, i.e. it can only be distributed under a open source software license.

Она и будет open source, я не намерен зажимать сорцы. Фирма их получит и может почитать на ночь при лампаде :) Только без меня она с ними вряд ли что-то сделает :)

anonymous
()
Ответ на: комментарий от anonymous

>Только без меня она с ними вряд ли что-то сделает :)

значит хреновая фирма :)

Pi ★★★★★
()
Ответ на: комментарий от anonymous

Если ты их даешь фирме под GPL и у тебя остается право их раздавать направо и налево, и у всех сотрудников фирмы будет такое право ( ох не верится мне в это ), то да. Иначе, нужно коммерческая лицензия.

devinull ★★
()
Ответ на: комментарий от devinull

> Если ты их даешь фирме под GPL и у тебя остается право их раздавать направо и налево, и у всех сотрудников фирмы будет такое право ( ох не верится мне в это ), то да. Иначе, нужно коммерческая лицензия.

Я ж говорю, приложение слишком специфическое. Что-то реально поиметь с этих сорцов не получится.

anonymous
()
Ответ на: комментарий от devinull

> > Глобальные переменные, которые не должны быть доступны из других модулей, нужно объявлять как static внутри *.c / *.cpp файлов.

> Внутри *.cpp им следует быть описанными внутри безымянного пространства имен, если уж на то пошло.

Можно и так, но можно и как static.

bbk123 ★★★★★
()
Ответ на: комментарий от devinull

> Если ты их даешь фирме под GPL и у тебя остается право их раздавать направо и налево, и у всех сотрудников фирмы будет такое право ( ох не верится мне в это ), то да. Иначе, нужно коммерческая лицензия.

С т.з. GPL, он отдаст свою прогу под GPL одному (юридическому) лицу - фирме-заказчику. И это отнюдь не дает _сотруднику_ этой фирмы прав использования и передачи этого софта, кроме как в рабочем процессе. Т.е. если ты написал тетрис, и отдал его фирме под ГПЛ - то секретарши могут играть в него только на рабочих компах с разрешения директора. А если унесут домой - это будет пиратство.

Более того, если он сам работает полный день на эту контору, то он вообще имущественными правами на софт не обладает (только авторскими). И тогда фирма может пользоваться, по сути, любым опенсорс софтом внутри, в т.ч. и с несовместимыми для распространения лицензиями - просто она не сможет этот софт продавать/раздавать.

anonymous
()
Ответ на: комментарий от anonymous

Месье юрист? Если так, то такая информация мне нравится.

devinull ★★
()
Ответ на: комментарий от Die-Hard

>Ничего "сложного" или "криминального" с точки зрения алгоритма в глобальных переменных нету.

Глобальные переменные - рассадник side-эффектов. С виду два одинаковых вызова метода - а поведение разное. Ибо глобальная переменная разная. Зевнуть ошибки с этим делом - очень легко.

А так - даже в GOTO ничего "сложного" и "криминального" нет :) Однако, слава Богу, от него отказались. Также, но лет на 10 спустя отказались, наконец, и от глобальных переменных.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> А так - даже в GOTO ничего "сложного" и "криминального" нет :) Однако, слава Богу, от него отказались. Также, но лет на 10 спустя отказались, наконец, и от глобальных переменных.

Я не отказался ни от того, ни от другого. И не жалею. И не глючит. Всё имеет право на жизнь, просто при разработке методом "тяпляп" некоторые конструкции потенциально опасны. Я не практикую метод "тяпляп".

anonymous
()
Ответ на: комментарий от anonymous

>Всё имеет право на жизнь

Угу. Даже бритьё топором.

>Я не практикую метод "тяпляп".

Опять угу. Видел я даже таких, кто у нас в лаборатории жратву рядом с тем же хромпиком хранил. Тоже ничего "тяпляп", типа, не практиковали.

И в программировании тоже. Я потом на тебя посмотрю, как ты в своём коде год спустя разбираться будешь. Про работу в команде я уже вообще молчу.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> И в программировании тоже. Я потом на тебя посмотрю, как ты в своём коде год спустя разбираться будешь. Про работу в команде я уже вообще молчу.

Мой код компактен, без лишних сущностей, с комментариями. А ваш - раздутый в угоду предрассудкам о вредности goto и пр. Вот ваш-то код как раз ужасен.

anonymous
()
Ответ на: комментарий от anonymous

>В Delphi у меня не было траблов прочитать глобальную переменную из нескольких тредов. Изменяет её значение всегда только один тред.

Тебе повезло. Проблем не будет с переменными с атомарным доступом (большинство числовых типов)

но будут со строками и структурами.

smartly ★★★
()
Ответ на: комментарий от anonymous

>Мой код компактен, без лишних сущностей, с комментариями. А ваш - раздутый в угоду предрассудкам о вредности goto и пр. Вот ваш-то код как раз ужасен.

Лет 15 назад я с тобой, может, и согласился бы :D Ну что же, подождём, посмотрим, что ты будешь петь ... нет, даже не через 10 лет, а когда попытаешься хотя бы полгода поработать в команде :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

2KRoN73:

> ...когда попытаешься хотя бы полгода поработать в команде :)

Ну да, _доля_ истины тут есть. Именно -- про команду. Чаще всего проще вообще отказаться от "рискованных" трюков в целях подтягивания наиболее слабого звена команды...

Но, уверяю, через несколько лет все это станет просто неактуально. Лемминги (и примкнувшие :) будут юзать "безопасные" языки, а Це останется уделом маргинальных профессионалов, которым заморочки с goto и глобальными переменными не страшны.

Кстати, _разумное_ использование goto и глобальных переменных не затрудняет, а _облегчает_ чтение программ (в т.ч. чужих).

Пример: вместо сотен передач полусотен параметров (альтенативы -- создания ad hoc полусотен структур с полусотней полей, или тысяч мелких функций с разумным числом параметров) для передачи значений в функции обычно лучше использовать сотню глобальных переменных с документированной мнемоникой.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Вдогонку:

> ...будут юзать "безопасные" языки ,,,

Имелось в виду, '...будут юзать "безопасные" языки и билдеры типа ВижуалСтудио...'.

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

В свободном доступе Qt3 для винды нет. Но как обычно, все что нужно лежит в осле.

Shmuma
()
Ответ на: комментарий от anonymous

Проблема в том, что её могут поменять во время использования. Например, при вычислении A*x + 2*A*y в первой части A будет одно, а во второй уже другое. Так что доступ к таким переменным надо прикрывать мутексом, что есть геморрой.

anonymous
()
Ответ на: комментарий от KRoN73

Что?!? Когда это от GOTO отказались? Никто от GOTO не отказался, наоборот, кроме самого goto появилось множество аналогичных конструкций - те же исключения и continuations. GOTO - полезнейшая фича, гораздо нужнее и важнее чем глобальные переменные.

anonymous
()
Ответ на: комментарий от KRoN73

Посмотрим, дурачок, что ты запоёшь, когда попробуешь без goto реализовать, например, интерптетатор байткода. Ну или любой другой тривиальный КА - включая лексеры и парсеры.

anonymous
()
Ответ на: комментарий от Die-Hard

>Пример: вместо сотен передач полусотен параметров

При возникновении таких ситуаций не о goto думать надо, а о полном рефакторинге кода.

Собственно, за последние лет 15 моей практики отказ от goto в тех местах, где он пришёлся бы к месту, приводил к рефакторингу и серьёзному упрощению и ускорению кода. Аналогичная ситуация и с глобальными переменными в последние 4..5 лет :)

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

>Что?!? Когда это от GOTO отказались?

Вот оно - новое поколение :D

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

>Посмотрим, дурачок, что ты запоёшь, когда попробуешь без goto реализовать, например, интерптетатор байткода.

А нормальные люди не путаются в применимости тех или иных алгоритмических методов под конкретные задачи.

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.