2012-02-08 2 views
1

Я разработчик Java, но мне пришлось сначала изучить C++, и я смущен некоторыми вещами. Я бы хотел создать глобальный заголовочный файл, в котором есть список переменных #define, которые будут постоянными во всем наборе, который я создаю. Я создал файл заголовка, и я добавил некоторые переменныеКак использовать файл заголовка без файла cpp

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

#define SM_START   1001; 
#define SM_PAUSE   1002; 
#define SM_STOP    1003; 
#define SM_SAVE    1004; 
#define SM_DISCARD   1005; 
#define SM_SETUP   1007; 


#endif // CONSTANTS_H 

Моя проблема заключается в том, что я не могу получить доступ к этим ...

Я включил файл заголовка, в котором мне нужно, но там нет для меня доступ к константам внутри него. Do I У вас есть, чтобы иметь .cpp-файл? есть ли способ доступа к постоянным переменным?

+1

В дополнение к прекрасным комментариям ниже, пожалуйста, не используйте #define для простых числовых констант, если вы можете избежать этого. Вы можете получить тот же эффект и гораздо более простые сообщения об ошибках, если вы вместо этого выполняете 'const int SM_START = 1001;' и т. Д. –

ответ

4

Первое: вы не должны ставить точки с запятой в конце #define. #define - это препроцессорная директива, означающая, что она в основном заменяет текстовое замещение определенного имени содержимым. Поэтому, если вы сделаете что-то вроде int a = SM_STOP + 1;, он будет предварительно обработан int a = 1003; + 1; с вашим кодом, который не то, что вы хотите.

Во-вторых: Заголовки, как правило, не скомпилированы, а только для включения в файлы *.cpp или другие заголовки (где #include - это еще раз текст). Поэтому да, у вас должен быть файл .cpp (ну не совсем, в первую очередь вы можете выбрать другое расширение, а во-вторых, вы могли бы даже дать компилятору заголовок как компиляционную единицу, но я бы посоветовал это сделать, по крайней мере, пока вы не знаете что ты делаешь). Однако вам не нужно иметь файл .cpp для ваших констант, просто #include ваш заголовок в любой файл, в который вы хотите использовать константы.

В-третьих: Почему вы используете здесь препроцессор? Это похоже на идеальную работу для перечисления. Затем вы можете поместить его в пространство имен/struct для удаления необходимости их префикса (с помощью SM_). Или вы можете просто использовать C++ 11 новый enum class, который ведет себя так же, как javas перечисления. Я бы избежал препроцессора там, где это возможно. Поскольку это просто замена текста, он не учитывает никаких областей охвата и т. Д., Что позволяет легко попасть в проблемы (например, с вашими точками с запятой).

2

Используйте #include <constants.h> или вне зависимости от того, как ваше имя файла должно включать этот файл. Кроме того, вам не нужны полуколоны. #defines - это текстовые замены, выполняемые в коде компилятором.

+1

"constants.h", а не - Компилятор имеет право не распознавать ваши включенные, если вы поместите их в < >, и я использовал более одного, чтобы ошибка –

+0

@TomTanner Согласовано. – Sid

+0

@TomTanner Хотя вы можете использовать -I/path/to/include, чтобы обойти это. – Sid

3

Проблема в том, что yuu имеет точки с запятой после #define. Это единственное, что мешает вам использовать ваши «константы», которые не являются технически постоянными; это определения препроцессора.

Логически компилятор C++ запускает текст вашей программы через препроцессор, текстовый фильтр, который выполняет директивы, начиная с #. Директива #define указывает препроцессору, чтобы найти все вхождения его левой части и заменить их дословно своей правой частью. В вашем случае он включает точки с запятой, что приводит к недействительным выражениям после замены.

Например,

if (command == SM_DISCARD) ... 

становится

if (command == 1005;) ... 

Это ошибка, и компилятор сообщает ему, как неверный синтаксис.

0

Вам не нужен файл cpp. Включение заголовка достаточно.

Препроцессор расширяет ваши определения тем, что после него.

SM_START станет 1001;

Поэтому выражение вида:

int x = SM_START; 

будет переводить

int x = 1001;; 

, которая до сих пор легально.

Но что точка с запятой может привести к неприятностям в чем-то вроде:

int x = SM_START * 10; 

, который будет расширен до:

int x = 1001; * 10; 

, которая явно незаконным.

Кроме того, директивы препроцессора не следует путать с глобальными. Даже если вы, вероятно, не должны использовать глобальные переменные, использование #defines, вероятно, хуже, чем определение class Global или просто использование переменных, сгруппированных в namespace.

+0

Итак, что я пытаюсь делать с хорошей практикой? Идея состоит в том, что эти «константы» будут внесены в lib, потому что для доступа к нему потребуется более одного процесса. Если есть лучший способ сделать это, пожалуйста, просветите меня, потому что я не уверен, правильно ли я делаю. – PTBG

+0

@ PTBG не очень. 1. Глобалы * вообще * плохие. 2. Если вы используете глобальные переменные, ставьте их как статические константные члены в классе или как внешние переменные в пространстве имен. –

Смежные вопросы