Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Изменяемые глобальные переменные


Автор: efpies 22.2.2012, 02:42
Много гуглил, ничего полезного не нашёл (в учебнике Дейтелов даже примера кода нет, всё, предполагается, должно быть понятно не так).

Ну окей.
Хочу задать масштаб отрисовки в одном месте (передавать как параметр в куче мест как-то накладно).

constants.h
Код

#ifndef ConstantsH
#define ConstantsH

double scale = 1.0;

#endif


Unit1.cpp
Код

#include "constants.h"
#include "Edge.h"

extern double scale;
 
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
     scale = 5.0;
     Edge *e;
     // Init
     e->draw();
     delete e;
}


Edge.h
Код

#include "constants.h"

extern double scale;

void Edge::draw ()
{
    canvas->PenPos = TPoint (x1*scale, y1*scale);
    canvas->LineTo(x1*scale, y2*scale);
}


scale в draw равен 1. Что я делаю не так?

Автор: t_gran 22.2.2012, 06:50
efpies, мне интересно как ваш код вообще работает. Вы посмотрите на эти строчки:

Unit1.cpp
Код

   // ...
   Edge *e;
   e->draw();
   delete e;
   // ...

Ничего странного не замечаете? Вы даже объект не создали, а пытаетесь вызвать метод draw, да ещё потом удаляете не созданный объект. Поразительно.  smile

Теперь по части extern.
Переменную как раз в заголовочном файле вы должны описать как extern, а реализовывать её уже в одном из cpp файлов. К примеру так:

constants.h
Код

#ifndef ConstantsH
#define ConstantsH
extern double scale;
#endif


Unit1.cpp
Код

#include "constants.h"
#include "Edge.h"
 
double scale = 1.0;

//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
     scale = 5.0;
     Edge *e = new Edge;
     // Init
     e->draw();
     delete e;
}


Edge.h
Код

#include "constants.h"

void Edge::draw ()
{
    canvas->PenPos = TPoint (x1*scale, y1*scale);
    canvas->LineTo(x1*scale, y2*scale);
}


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

Автор: efpies 22.2.2012, 10:38
Цитата(t_gran @ 22.2.2012,  06:50)

Ничего странного не замечаете? Вы даже объект не создали, а пытаетесь вызвать метод draw, да ещё потом удаляете не созданный объект. Поразительно.  smile


Нет, не замечаю, просто не хочу сюда копировать 10 строк инициализации, к делу не относящейся smile

Действительно, так работает, спасибо. Что интересно, это расходится с http://www.rsdn.ru/forum/cpp/2706624.1.aspx статьёй, или я чего-то не понимаю.

Автор: mes 22.2.2012, 12:31
Цитата(efpies @  22.2.2012,  09:38 Найти цитируемый пост)
Что интересно, это расходится 

расходится в чем ?

Автор: t_gran 22.2.2012, 13:59
Цитата

Нет, не замечаю, просто не хочу сюда копировать 10 строк инициализации, к делу не относящейся 

Не подумайте, что придираюсь, но тогда и delete к делу не относится.

Цитата

Что интересно, это расходится с вот этой статьёй, или я чего-то не понимаю.

Абсолютно не расходится. Вы просто не так поняли. Заметьте, что в статье фигурируют только cpp файлы. О заголовочных файлах там ни слова. К тому же, нужно чётко понимать, что такое h файл, и что переменные в них никогда не объявляются.

Автор: mes 22.2.2012, 14:36
Цитата(t_gran @  22.2.2012,  12:59 Найти цитируемый пост)
что такое h файл, и что переменные в них никогда не объявляются. 

 smile 

Автор: t_gran 22.2.2012, 14:43
mes, поясните. Я что-то не то написал? Или вы к тому что я не так выразился и вместо инициализации употребил слово объявление?

Автор: feodorv 22.2.2012, 16:24
Цитата(t_gran @  22.2.2012,  13:59 Найти цитируемый пост)
нужно чётко понимать, что такое h файл, и что переменные в них никогда не объявляются. 

Деление кода на .c-часть и .h-часть в достаточной степени является вопросом соглашения. Не принято объявлять переменные в заголовочных файлах, но это не значит, что там их объявлять совсем нельзя. Можно, но для ограниченного круга задач.

Можно ведь и .c-файл заинклюдить:
Код

#include "mycode.c"

никто не запрещает. 

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

#include "mycode.h"
#include "mycode.c"

можно весь код из mycode.c (вместе с объявлениями переменных etc) запихнуть в mycode.h. Получится просто
Код

#include "mycode.h"

Но нужно, конечно, понимать, что и зачем делаешь smile 

Автор: mes 22.2.2012, 16:42
Цитата(t_gran @  22.2.2012,  13:43 Найти цитируемый пост)
Я что-то не то написал? 

 
Цитата

 никогда не

не верю что нельзя определить переменную в хидере smile

ну и маленькое замечание, в данном контексте не объявление, а определение
  объявление:     extern value;
  определение:  value; или extern value =0;

и определение включает в себя объявление, но не наоборот.. 





Автор: t_gran 22.2.2012, 18:02
Цитата

не верю что нельзя определить переменную в хидере 

ну и маленькое замечание, в данном контексте не объявление, а определение
  объявление:     extern value;
  определение:  value; или extern value =0;

Добро

Автор: efpies 23.2.2012, 00:01
Цитата(t_gran @  22.2.2012,  13:59 Найти цитируемый пост)
Не подумайте, что придираюсь, но тогда и delete к делу не относится.

ну да, Вы правы, но с десятью другими было бы все 11 smile


Цитата(mes @  22.2.2012,  12:31 Найти цитируемый пост)
расходится в чем ? 

Цитата(RSDN)

Допустим, у нас есть два модуля A.cpp и B.cpp. В модуле A определена целая переменная i вне всех классов и функций:
int i = 2;

Такая переменная называется глобальной. В файле A она видна от точки определения и до конца файла. Однако в модуле B эта переменная не видна. И если вдруг нам потребуется в модуле B присвоить ей другое значение, у нас возникнут некоторые проблемы. Нельзя просто написать:
i = 1;

В этом случае компилятор при обработке модуля B «не видит» модуль A и ничего не знает об определенной там переменной, поэтому мы получим сообщение о неопределенной переменной. Также нельзя написать:
int i = 1;

Такая запись является повторным определением. Потому модуле B надо объявить переменную следующим образом:
extern int i;

После этого можно использовать переменную i в файле B любым разрешенным способом.


Экстраполируя на мою задачу, A = constants.h, а B = Unit1.cpp. Я это понял так, раз объявляю её в A, а использовать хочу в B.

Автор: mes 23.2.2012, 01:09
Цитата(efpies @  22.2.2012,  23:01 Найти цитируемый пост)
 у нас есть два модуля A.cpp и B.cpp

Цитата(efpies @  22.2.2012,  23:01 Найти цитируемый пост)
Экстраполируя на мою задачу,

модуль это не отдельный файл, а грубо .cpp со всеми включенными хидерами... 

и если быть точнее, не модуль, а единица трансляции..

Автор: efpies 23.2.2012, 01:16
Вот спасибо smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)