Учи понятие «единица компиляции».
Два варианта.
a) Несколько единиц компиляции (основной вариант, когда идёт активная разработка проекта). Тогда в хедере каждую переменную отмечаешь модификатором extern — «переменная есть, но где-то в другом месте». В одной из единиц компиляции объявляешь переменные, уже без extern.
Насколько мне известно, защита от двойного включения для extern-переменных не важна, но, например, для классов или функций ой как пригодится.
///// unit.h /////
#ifndef UNIT_H
#define UNIT_H
extern int myVar;
#endif
///// unit.cpp /////
#include "unit.h"
int myVar;
///// main.cpp /////
#include "unit.h"
int main()
{
myVar = 1;
}
б) Одна большущая единица компиляции (в такой вид часто преобразуют библиотеки перед выпуском). Тогда достаточно оградить каждый хедер от двойного включения, и всё в порядке.
///// unit.h /////
#ifndef UNIT_H
#define UNIT_H
int myVar;
#endif
///// main.cpp /////
#include "unit.h"
int main()
{
myVar = 1;
}
ЗЫ. Когда я писал ответ, кода ещё не было. А тут он взял и пришёл. Для переменных (SYMBOL_WIDTH, LINE_HEIGHT) решение то самое. А для констант вариантов несколько.
Путь сишный.
#define LEFTPANEL 200
ВОЗМОЖНО для литеральных констант, и особенно классно работает с текстовыми строками (например, "[" TEXT "]").
НЕДОСТАТКИ: это препроцессор, и при пересечении имён будет нехорошо.
Путь перечислимый.
enum {
LEFTPANEL = 200
};
ВОЗМОЖНО для констант, влезающих в int.
НЕДОСТАТКИ: возможны приколы с кроссплатформенностью, если на отдельных платформах константа вылезет за грань int.
Путь переменный.
extern const int LEFTPANEL;
....
const int LEFTPANEL = 200;
ВОЗМОЖНО для любых констант.
НЕДОСТАТКИ: нет вычисления при компиляции. Только линкер знает, что это 200.
Путь C++11.
constexpr int LEFTPANEL = 200;
ВОЗМОЖНО для литеральных констант.
НЕДОСТАТКИ: только C++11.
Путь «на рывок»
static const int LEFTPANEL = 200;
ВОЗМОЖНО для всех литеральных типов, но при этом может создавать дублирующиеся переменные: так, в Borland будет дублироваться всё сверх int — и, соответственно, не допускать предкомпилированных заголовков, ибо создаётся код.
НЕДОСТАТКИ: семантика зависит от компилятора и типа, ради чего и сделали constexpr.