проблема с глобальными константами в c ++ - PullRequest
3 голосов
/ 05 октября 2009

У нас есть этот набор «служебных» констант, определенных в серии файлов. Проблема возникает из-за того, что СЛИШКОМ МНОГИЕ файлы содержат эти глобальные константные файлы, что, если мы добавим константу в один из этих файлов и попытаемся создать ее, она создаст всю библиотеку, что займет более часа. *

Может ли кто-нибудь предложить лучший способ для этого подхода? Это будет с благодарностью.

Ответы [ 4 ]

7 голосов
/ 05 октября 2009

Во-первых, если вы определяете их непосредственно в заголовке, я бы предложил вместо этого разделить их extern const, а затем определить их в файле cpp:

//in .hpp:
extern const std::string foo;

//in .cpp:
const std::string foo = "FOO";

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

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

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

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

2 голосов
/ 05 октября 2009

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

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

Другим решением было бы иметь файл .h, который имеет доступ к карте имени / значения строки. Затем в .cpp файле этой карты / аксессора вы можете вставить новые значения. Каждое новое значение, которое вы вводите, требует перекомпиляции только 1 файла.

Другое решение - нигде не включать заголовочный файл. Просто введите необходимые переменные в каждый файл .cpp.

1 голос
/ 05 октября 2009

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

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

0 голосов
/ 05 октября 2009

(Правка. Я не думал о внешних константах. Действительно, моя идея довольно глупа.)

(Правка. Моя «глупая» идея макроса на самом деле экономит время сборки при добавлении констант. Спасибо за указание на это, Брайан!)

Используйте параллельное здание: -)

Серьезно, я думаю, что одним из решений было бы создание другого заголовка с именем utility_ex.hpp или чего-то еще, где вы добавляете новые константы, которые вы время от времени сливаете в utility.hpp (или как называется ваш текущий заголовок констант утилит).

Другим (менее эффективным) решением было бы иметь такой макрос:

#define constant(name) get_constant(#name)
    // # means turn name into a string literal

int get_constant(const char *name);

Теперь предположим, что вы хотите, чтобы MAX_CUSTOMERS был определен как 100. Вы можете сказать:

constant(MAX_CUSTOMERS)

в коде. В коде get_constant вы можете иметь:

int get_constant(const char *name) {
    if (!strcmp(name, "MAX_CUSTOMERS"))
        return 100;

    //shouldn't happen
    return -1;
}
...