С++ Рекомендации для констант - программирование
Подтвердить что ты не робот

С++ Рекомендации для констант

У меня есть целая группа констант, к которой я хочу получить доступ в разных частях моего кода, но я хочу иметь легкий доступ в целом:

static const bool doX = true;
static const bool doY = false;
static const int maxNumX = 5;

и т.д..

Итак, я создал файл под названием "constants.h" и закрепил их там, а # включил его в любой файл, который должен знать константу.

Проблема в том, что это ужасно для времени компиляции, так как каждый раз, когда я изменяю константу, все файлы, которые требуется восстановить с помощью константы .h, должны быть восстановлены. (Также, как я понимаю, поскольку они являются статическими, я генерирую копию doX/doY/maxNumX в коде каждый раз, когда включаю constants.h в новый .cpp, приводя к килобайтам потерянного пространства в скомпилированном EXE - есть ли способ увидеть это?).

Итак, я хочу решение. Тот, который не "объявляет константы только в файлах, которые их используют", если это возможно.

Любые предложения?

4b9b3361

Ответ 1

Единственная альтернатива - сделать ваши константы extern и определить их в другом файле .cpp, но вы потеряете потенциал для оптимизации, потому что компилятор не будет знать, какое значение они имеют при компиляции каждого .cpp`.,

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

Наконец, что static не требуется, поскольку по умолчанию const глобальные переменные static в С++.

Ответ 2

Вы объявляете их как extern в заголовке и определяете их в файле реализации.

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

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

EDIT:

С++ - иш способ сделать это фактически упаковывает их в класс:

//constants.h
class Constants
{
public:
   static const bool doX;
   static const bool doY;
   static const int maxNumX;
}

//constants.cpp
const bool Constants::doX = true;
const bool Constants::doY = false;
const int Constants::maxNumX = 5;

Ответ 3

Я думаю, что ваше базовое предположение отключено.

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

Зачем группировать все константы в одном заголовке? Это не имеет смысла. Это примерно такая же идея, как заголовок "global.h", чтобы легко включать каждую отдельную зависимость.

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

class File {
public:
  enum class Mode {
    Read,
    Write,
    Append
  };

  File(std::string const& filename, Mode mode);

  // ...
};

В этом случае вполне естественно, что эти константы живут в том же заголовке, что и класс, к которому они привязаны (и даже внутри класса).

Другая категория констант - это те, которые пронизывают всю заявку. Например:

enum class Direction {
  Up,
  Down,
  Right,
  Left,
  Forward,
  Backward
};

... в игре, где вы хотите выразить движение объектов относительно направления, в котором они находятся.

В этом случае создание одного заголовочного файла для этого определенного набора констант в порядке.

И если вы действительно беспокоитесь об объединении этих файлов вместе:

constants/
  Direction.hpp
  Sandwich.hpp
  State.hpp

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

Ответ 4

В чем проблема с этим использованием?
Не объявляйте тип static в заголовочном файле, он не делает то, что вы думаете.

Когда вы объявляете статический файл в заголовке, копия этой переменной создается в каждом Translation Unit (TU), где вы включаете эту заголовочный файл, SO, каждый TU видит другую переменную, это противоположно вашему ожиданию наличия глобального.

Рекомендуемое решение:
Вы должны объявить их как extern в заголовочном файле и определить их в одном файле cpp, включая заголовок с extern в каждом файле cpp, где вы хотите получить к ним доступ.

Хорошее чтение:
Как использовать extern?

Ответ 5

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

//constants.h
class Constants
{
public:
  static bool doX();
  static bool doY();
  static int maxNumX();
};

//constants.cpp
bool Constants::doX() { return true; }
bool Constants::doY() { return false; }
int Constants::maxNumX() { return 42; }

Преимущество такого подхода заключается в том, что вы только перекомпилируете все, если вы добавляете/удаляете/изменяете объявление метода в заголовке, а при изменении значения, возвращаемого любым методом, требуется только компиляция констант .cpp(и, конечно, привязка).

Как и в большинстве случаев, это может быть или не быть лучшим в вашем конкретном случае, но это еще один вариант.

Ответ 6

Прямым способом является создание неконтактных символов:

const bool doX = true;
const bool doY = false;
const int maxNumX = 5;

Эти значения будут заменены компилятором с заданными значениями. Это самый эффективный способ. Это также, конечно, приводит к перекомпиляции, как только вы изменяете или добавляете значения. Но в большинстве случаев это не должно приводить к практическим проблемам.

Конечно, существуют разные решения:

  • Используя static const s (или статические члены класса const), значения могут быть изменены без перекомпиляции всех файлов, на которые ссылаются, но тем самым значения сохраняются в сегменте данных const, который будет вызываться во время выполнения, а не разрешается при компиляции. Если производительность исполнения не является проблемой (как и для 90% наиболее типичного кода), то ОК.

  • Прямой метод С++ использует класс enums, а не глобальные идентификаторы const (как отмечал мой Mathieu). Это более типично, и кроме того, он много работает как const: символы будут разрешены во время компиляции.