Есть ли способ определить, когда файловые зависимости "случайно" удовлетворены? - PullRequest
8 голосов
/ 17 июля 2011

Допустим, есть три заголовка AAA.h, BBB.h и MyLib.h.MyLib.h должен включать в себя AAA.h и BBB.h для правильной работы.

Теперь, просто так получается, что BBB.h также включает в себя AAA.h, но это строго из-за реализации, детали, о которой MyLib.h не нужно заботиться.

Однако по ошибке автор MyLib.h пренебрегает включением AAA.h и никогда не замечает.Насколько я знаю, это обычно не приводит к ошибке или предупреждению.Позже кто-то изменяет детали реализации BBB.h так, что AAA.h больше не нужен и, следовательно, удаляется.Теперь MyLib не компилируется, потому что внутренности библиотеки BBB изменились.

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

Ответы [ 2 ]

2 голосов
/ 18 июля 2011

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

Заголовки общедоступного интерфейса не должны содержать ненужных определений.

ТамРазличные трюки, чтобы сделать вещи без включаемых файлов.Например, вы можете объявить теги struct вручную, если вам просто нужен указатель (библиотеки, которые только определяют typedef, расстраивают это), и вы можете использовать _Bool вместо bool, чтобы избежать <stdbool.h>.К сожалению, многие важные типы, такие как size_t и uint32_t, определены только в заголовках.

Некоторые пакеты заходят настолько далеко, что определяют свои собственные foo_uint32_t с помощью configure, поэтому им не нужно включать <stdint.h> вих заголовки общедоступного интерфейса.Это довольно сложно, так как типы должны быть одинаковыми, чтобы избежать путаницы: даже если sizeof(unsigned int) == sizeof(unsigned long) == 4, это разные типы.Следовательно, это может не стоить того.

2 голосов
/ 18 июля 2011

Вы иллюстрируете, почему включение заголовков - отстой в качестве метода импорта пространств имен.

Единственное решение, которое я вижу, - это дисциплина.Стандартные функции библиотеки требуют, чтобы вы включили соответствующий заголовок, ваши проекты должны принять тот же стандарт.Заголовки, такие как MyLib.h, должны содержать только типы, которые он определяет, и прототипы его функций.Если для выполнения своей работы необходимо использовать определенный тип, заголовок должен быть включен явно, поэтому, если ему нужно определение из AAA, оно должно включать AAA.h, а если ему нужно какое-то определение из BBB, то оно должно включать BBB.h, аналогично любые файлы реализации (скажем, MyLib.c) должны явно включать все заголовки для любых определений, которые он использует, независимо от того, уверен ли, что MyLib.h также включает их. Никогда не предполагайте, что заголовок определяет что-то неявно путем включения других заголовков.

Это легко проверить с помощью IDE, которая обычно сообщает вам, где определено имя, и, таким образом, вы можете легко понятькоторый включает файл для использования.Могут быть доступны инструменты, которые выполняют такую ​​проверку.

...