Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
Строитель
460 / 77 / 4
Регистрация: 18.06.2010
Сообщений: 514
1

Результат работы над ошибками по поводу глобальных переменных на с++

09.01.2017, 08:56. Показов 3214. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Данная статья выйдет в топ. По теме как делать глобальные переменные. Так как имею опыт в написание статей под нужды людей.

Хочу рассказать историю и опыт своих исследований по поводу глобальных переменных

Начнем с того, зачем нам нужны глобальные переменные?
Для того, чтобы необходимое установленное значение в переменной могло использоваться в разных частях вашего кода! И в разных файлах СПП.

Можно ли обойтись без глобальных переменных?
Нет! Потому что существуют такие задачи, как установка конфигурационных настроек для работы всего проекта. Например, такие как: Ширина и высота различных окон и панелей. Также установка различных переключателей для изменения стиля поведения работы приложения. Также перевод на другие языки ваше приложение. Где каждая команда на вашем языке будет обозначаться глобальной переменной, в которую будет записано словосочетание команды и потом при переключении языка, в эти переменные будут записываться слова различных языков. Поэтому для больших проектов это нужно предусмотреть на этапе создания проектов.

Сейчас расскажу о граблях, на которые наступал при создании глобальных переменных

1. Название маленькой переменной в коде какого-нибудь метода(функции) совпадало с названием глобальной переменной. И это приводило к тому, что глобальные переменные перезаписывались и меняли свое значение. При таком сценарии трудно искать ошибку. Однако есть выход. Мы просто договоримся назвать глобальные переменные с какой-нибудь приставкой. Например, с приставкой GLOB, GLOBperemannaya1… GLOBperemannaya1 и так далее. И Вы уже случайно не сможете добавить в код эту глобальную.

2. В С++ встречались проблемы по поводу #include-ов. Ошибка на которую все поголовно попадаются – это прописать в заголовочном файле (file.h) код присвоение значения переменным. То есть нельзя заниматься инициализацией переменных в заголовочных файлах. Инициализация - это присвоение переменным значение. Но объявлять переменные только через приставку: extern

В заголовочном файле (file_name.h) нужно заниматься тем, что объявлять существование функций(методов) и переменных. Но переменные объявлять только через: extern int GLOBperemen1;
Объявлять функции нужно для того, чтобы функции(методы) были видны файлам СПП через подключающие заголовки: #include "file_name.h"

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

Поэтому у Вас есть два выбора создания глобальных переменных: Или одноименные переменные или через структурную переменную создавать свои коллекции глобальных переменных. Есть еще способ, как создать глобальную переменную через класс, но он оставляет за собой очень длинное название, подробнее обсуждалось тут: Как лучше сделать глобальную переменную?
Глобальные переменные через класс имеют дополнительную процедуру вызова, что теоретически увеличивает количество ступеней до получения и присвоения значения переменной. Что может влияет на скорость работы. Это еще не проверено, на сколько, идут тормоза. Но просто имейте это в виду. Надо бы еще структурную переменную переменную проверить на скорость.
Вот собственно код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Файл: Global.h - для объявление переменных и методов, чтобы не писать лищнего кода в файлах спп
 
#ifndef _B_H //для исключения второго объявления
#define _B_H //для исключения второго объявления
 
//Одноименные глобальные переменные, в заголовочных файла (.h) объявляем только через приставку extern
extern int GLOBperemen1;//Одноименная Глобальная переменная 1
extern int GLOBperemen2;//Одноименная Глобальная переменная 2
extern int GLOBperemen3;//Одноименная Глобальная переменная 3
extern int GLOBperemen4;//Одноименная Глобальная переменная 4
extern int GLOBperemen5;//Одноименная Глобальная переменная 5
 
//Структурная глобальная переменная Global
struct Global
{
    int p1;//Глобальная переменная 1
    int p2;//Глобальная переменная 2
    int p3;//Глобальная переменная 3
    int p4;//Глобальная переменная 4
    int p5;//Глобальная переменная 5
};
 
extern Global g; // объявление глобальной структурной переменной для всех файлов спп
void GlobUst();//Объявление глобальной структурной переменной для всех файлов спп
 
void MyFunc();//Объявляем функцию из файла MyKod2.cpp, чтобы он был виден в файле MyKod1.cpp
 
#endif //для исключения второго объявления
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Файл: Global.cpp - Для инициализации - присвоения значения переменным.
 
#include "Global.h"
 
int GLOBperemen1=1;//Одноименная Глобальная переменная 1
int GLOBperemen2=2;//Одноименная Глобальная переменная 2
int GLOBperemen3=3;//Одноименная Глобальная переменная 3
int GLOBperemen4=4;//Одноименная Глобальная переменная 4
int GLOBperemen5=5;//Одноименная Глобальная переменная 5
 
Global g; // определение глобальной структуры
 
void GlobUst() // метод установки значения переменным для структурной переменной
{
    g.p1=1;//Глобальная переменная 1
    g.p2=2;//Глобальная переменная 2
    g.p3=3;//Глобальная переменная 3
    g.p4=4;//Глобальная переменная 4
    g.p5=5;//Глобальная переменная 5
}

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//MyKod1.cpp - рабочий код программы
 
#include <iostream>//Подключаем библиотеку для работы с определенным кодом типа std::cout system("pause"); и прочее
#include <stdlib.h>//Подключаем библиотеку для работы с определенным кодом типа std::cout system("pause"); и прочее
 
#include "Global.h"//Заголовочный файл, который подключается ко всем файлам спп
 
int main()
{
    GlobUst(); // Запускаем метод в котором задаются значения переменным. Так как методы работаю по ходу кода.
 
    MyFunc();
    std::cout << GLOBperemen1 << ' ' << g.p1 << ' ' << g.p2 << std::endl;
    
    system("pause");
    return 0;
}

C++
1
2
3
4
5
6
7
8
//MyKod2.cpp - рабочий код программы
 
#include "Global.h"//Заголовочный файл, который подключается ко всем файлам спп
 
void MyFunc()
{
    GLOBperemen1=GLOBperemen2+GLOBperemen3;
}
Жду комментарии по поводу моих выводов!


 Комментарий модератора 
Ознакомьтесь с правилами.

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

Спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.01.2017, 08:56
Ответы с готовыми решениями:

Работы над ошибками
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics,...

Сохранение глобальных переменных между сеансами работы с книгой
Привет! Спрошу, скорее всего, глупость, и заранее извиняюсь за это: беглый поиск в гугле при...

Рассмотреть программу, написать имена глобальных переменных, локальных переменных, формальных параметров
Program P1; var s:string; procedure P(var s:string) ; var i, j : integer; ...

Получить результат работы функции в виде нескольких переменных
Один из способов с выводом результата в параметры: void func(int* res1, int* res2, int par1, int...

13
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,884
Записей в блоге: 1
09.01.2017, 09:02 2
Цитата Сообщение от infobos Посмотреть сообщение
Можно ли обойтись без глобальных переменных?
Нет!
Без глоб. пер. обойтись всегда можно, роль глоб. пер. в оптимизации.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.01.2017, 11:03 3
Цитата Сообщение от _stanislav Посмотреть сообщение
Без глоб. пер. обойтись всегда можно, роль глоб. пер. в оптимизации.
Ну да. Чтобы не хранить в каждом инстансе кучу указателей на настройки.

Добавлено через 30 минут
Цитата Сообщение от infobos Посмотреть сообщение
Мы просто договоримся назвать глобальные переменные с какой-нибудь приставкой. Например, с приставкой GLOB, GLOBperemannaya1… GLOBperemannaya1 и так далее. И Вы уже случайно не сможете добавить в код эту глобальную.
В принципе идейка здравая для С.
Для С++ лучше сгруппировать их в структуры а потом сделать один/несколько классов которые имеют эти структурки переменные статическими полями. И с extern парится не надо и инструмент для групповой установки/передачи нестандартных настроек.
ну к примеру:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//FormatSettings.h файл
srtuct TFloatFormat{
        char DecPoint='.';
        char  Exp='e'
        char Positive='+'
        char Negative='-'
        unsigned char Precision=3;
};
srtuct TStringFormat{
        enum TLineSeparator{CR,LF,CRLF,LFCR};
         char  CR='\r';
         char  LF='\n';
         char Terminator='\0';
         TLineSeparator LineSeparator=CRLF; 
};
 
struct FormatSettings{
        static TStringFormat String;
        static TFloatFormat  FLoat;
}
// FormatSettings.cpp файл
#include <FormatSettings.h>
TStringFormat FormatSettings::String;
TFloatFormat FormatSettings::Float;
//использование в другом cpp:
#include <iostream>
#include <FormatSettings.h>
int main(){
float a=-5;
std::cout<<(a<0?FormatSettings::Float.Negative: FormatSettings::Float.Positive);
TFloatFormat Backup=FormatSettings::Float;//запомнили настройки
FormatSettings::Float.DecPoint=',';
FormatSettings::Float.Exp='E';
DoSomething(); //сделали что то с нестандартными настройками
FormatSettings::Float = Backup; // воcстановили настройки;
};
//Так же можно делать перегруженные функции которые работают с дефаултными и недефаултными настройками
inline void DoSomething() {DoSomesing(FormatSettings::Float);}
void DoSomesing(TFloatFormat& Format){
     // чаво то делаем пользуя формат
}
Добавлено через 7 минут
Ну в общем то же самое только с пользованием возможностей плюсов для более компактной записи и более удобного использования.
0
Неэпический
18100 / 10686 / 2061
Регистрация: 27.09.2012
Сообщений: 26,897
Записей в блоге: 1
09.01.2017, 11:17 4
А если одна глобальная переменная нужна для инициализации другой глобальной переменной в другой единице трансляции? Вот боль!
0
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
09.01.2017, 11:28 5
[quote="Fulcrum_013;9983779"]
Цитата Сообщение от infobos Посмотреть сообщение
Название маленькой переменной в коде какого-нибудь метода(функции) совпадало с названием глобальной переменной. И это приводило к тому, что глобальные переменные перезаписывались и меняли свое значение.
C++
1
2
3
4
5
6
7
8
9
int n=1;
void f(){
    int n;
    n = 123; // глобальная переменная  n  при этом не изменится 
 
    cout << "    global : " << ::n << endl;
    cout << "    local : " << n << endl;
 
}
Добавлено через 7 минут
Цитата Сообщение от infobos Посмотреть сообщение
глобальные переменные с какой-нибудь приставкой. Например, с приставкой GLOB, GLOBperemannaya1… GLOBperemannaya1 и так далее.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
В принципе идейка здравая для С.
Для С++ лучше сгруппировать их в структуры
Также в C++ можно использовать пространство имен.

C++
1
2
3
4
5
6
7
8
9
10
11
//  если не добавлять такую директиву   using namespace std;
// то я могу использовать и вектор из стандартной библиотеки 
std::vector<int> a;
 
// и могу определить свой тип с именем   vector 
struct vector{
  double x;
  double y;
};
 
vector v2;
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.01.2017, 11:33 6
Alex5, По всей видимости имелось в виду что в скопе в котором объявлена одноименна переменная "магическим" образом значение которое ожидалось прочитать из глобальной переменной внезапно оказывалось абсолютно другим.
0
Неэпический
18100 / 10686 / 2061
Регистрация: 27.09.2012
Сообщений: 26,897
Записей в блоге: 1
09.01.2017, 11:36 7
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
значение которое ожидалось прочитать из глобальной переменной
Для этого есть ::
C++
1
::SomeGlobalName
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.01.2017, 11:36 8
Цитата Сообщение от Alex5 Посмотреть сообщение
Также в C++ можно использовать пространство имен.
Можно. Только все переменные пространства имен одним махом не скопируешь и в функцию одним аргументом не передашь. А как известно по Законам Мэрфи как только появляется некие общие правила (глобальные настройки в данном случае) тут же появляются исключения из оных правил.
0
Неэпический
18100 / 10686 / 2061
Регистрация: 27.09.2012
Сообщений: 26,897
Записей в блоге: 1
09.01.2017, 11:38 9
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
и в функцию одним аргументом не передашь
А зачем его передавать, если оно глобальное?
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.01.2017, 11:47 10
Цитата Сообщение от Croessmah Посмотреть сообщение
Для этого есть ::
Есть. Но и сам кучу раз наступал на грабли с совпадением имен методов и глобальных функций и совпадением имен полей/свойств и локальных переменных/аргументов метода. И очень долго каждый раз удивлялся почему метод вызывающий по идее одноименную глобальную функцию входит в рекурсию и т.п, и так удивляешься пока имя метода не прочитаешь.

Добавлено через 6 минут
Цитата Сообщение от Croessmah Посмотреть сообщение
А зачем его передавать, если оно глобальное?
Потому как только появляется нечто глобальное что подходит вроде бы всему тут же появляются исключения из правил где какая то мелочь совсем не такая. Т.е. гораздо практичнее обычно получается все глобальные настройки пользовать как дефаултные если не указываются другие.
0
Строитель
460 / 77 / 4
Регистрация: 18.06.2010
Сообщений: 514
09.01.2017, 14:45  [ТС] 11
Цитата Сообщение от _stanislav Посмотреть сообщение
Без глоб. пер. обойтись всегда можно, роль глоб. пер. в оптимизации.
Позволю себе процетировать.
Данный ответ можно перевести, цетирую:
Да можно... Теоретически...
Рубить мясо топором...
Держа тапор одним пальцем левой руки - одним мезинцем.
Балансируя тапор на одном пальце и отклонением направлять в сторону мяса.

Пожалейте программиста. Добавив одну модификацию придется много процедур, функций и методов переписывать, если хоть что-то изменится в программе.
0
671 / 217 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
10.01.2017, 08:12 12
Цитата Сообщение от infobos Посмотреть сообщение
Можно ли обойтись без глобальных переменных?
Нет! Потому что существуют такие задачи
хорошо, огромное спасибо за инфу.

Теперь жду следующую статью про жизненноважную необходимость оператора goto и setjmp (разумеется в С++, а не С)
0
Неэпический
18100 / 10686 / 2061
Регистрация: 27.09.2012
Сообщений: 26,897
Записей в блоге: 1
10.01.2017, 11:30 13
Цитата Сообщение от dailydose Посмотреть сообщение
про жизненноважную необходимость оператора goto
Наслаждайтесь: Goto - за и против
2
671 / 217 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
10.01.2017, 11:40 14
Croessmah,
пожалуй единственное, что можно вынести из того топика:
Цитата Сообщение от Убежденный Посмотреть сообщение
Мой вариант ответа третий: goto - зло, но иногда попытки избежать
его использования приводят к еще большему злу.
0
10.01.2017, 11:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.01.2017, 11:40
Помогаю со студенческими работами здесь

О глобальных переменных
Народ всем привет! Я только начал программировать на Visual Basic 2005 express edition. Помогите с...

Работа над ошибками
#include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; int main() { double a,b,c;...

Работа над ошибками
По сути, мне надо чтобы система дешифровала предложения и вроде бы вчера работала а сегодня...

Работа над ошибками
Что не так с кодом? #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru