Размещение включений во всех нужных местах

#c #gcc #linker #header-files

#c #gcc #компоновщик #заголовочные файлы

Вопрос:

Итак, мы используем #include для указания компилятору / компоновщику, где найти весь соответствующий код для класса.

Взгляните на это:

 ClassC.h:
    #include "ClassA.h";

ClassD.h:
    #include "ClassC.h"
 

Допустим, мы используем ClassA в нашем ClassD , но таким образом, который никоим образом не связан ClassC с. Мы неявно включили его, включив ClassC , поэтому ошибка не выдается. Однако, если код изменится и ClassC больше не понадобится (и мы удалим #include "ClassC.h" его из-за этого), мы получим неопределенную ошибку ссылки, поскольку ClassA теперь на нее нет ссылок.

Есть ли способ заставить компилятор / компоновщик просматривать каждый из * .cpp и назначенный * .h независимо, не заглядывая во включенные файлы .h?

Если бы это было так, он бы не просматривал ClassC.h и не видел, что он включает ClassA.h , а выдавал ошибку или, по крайней мере, предупреждение, сообщающее мне, что я не включил ClassA.h . Это имеет больше смысла, поскольку, насколько ClassD известно классу, ClassA они ClassC не связаны друг с другом (в соответствии с установленным предположением, которое я использую ClassA независимо ClassC ).

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

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

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

Я знаю, что немного все усложняю, но мне это кажется хорошей практикой.

Это даже хорошая идея, и может ли она каким-то образом быть установлена в параметрах компилятора / компоновщика (например, компилятор GNU gcc в CodeBlocks)?

Комментарии:

1. Вы должны проверить включение охранников. en.wikipedia.org/wiki/Include_guard

2. Я знаю, что защита включения великолепна и не позволяет вам включать одни и те же две вещи в проект. Я хочу иметь возможность включать что-то в свой код в 10 разных местах, если это необходимо, несмотря на то, что компилятор / компоновщик использует только первый, до которого он добирается.

3. Я не понимаю, ни какую проблему вы пытаетесь решить, ни решение, которое вы предлагаете

4. «хочу иметь возможность включать что-то в свой код в 10 разных местах» что мешает вам сделать это?

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

Ответ №1:

Допустим, мы используем ClassA в нашем ClassD, но таким образом, который никоим образом не связан с ClassC. Мы неявно включили его, включив ClassC, поэтому ошибка не выдается. Однако, если код изменится и ClassC больше не понадобится (и мы удалим #include «ClassC.h» из-за этого), мы получим неопределенную ошибку ссылки, поскольку ClassA теперь не ссылается.

Если вам нужно использовать ClassA в вашем ClassD , то явно #include "ClassA.h" в вашем ClassD.h . Не полагайтесь на неявные цепочки включений.

Комментарии:

1. Я хочу это сделать. Я просто хочу знать, есть ли способ для компилятора выполнить проверку для меня.

2. @Karlovsky120: На данный момент я не знаю, что вы точно имеете в виду. Компилятор не обладает экстрасенсорными способностями, чтобы угадать, какие заголовки вам нужны. В любом случае, если вы не включите требуемые заголовки, вы получите ошибки компилятора или компоновщика.

3. Я в основном имел в виду, может ли компилятор / компоновщик определить, было ли включение явным или неявным, и выдать предупреждение о том, что это было неявное включение. Это может быть сложно сделать, поскольку некоторые неявные включения (например, унаследованные от родительского класса) будут в порядке, поскольку они всегда будут присутствовать.

4. @Karlovsky120 Таким образом, вы имеете в виду, что используете класс X, но напрямую не включаете его заголовок и полагаетесь на неявные цепочки включения. Я не знаю, есть ли такой инструмент, доступный сегодня.

5. Сейчас я провел некоторое исследование, и некоторые статические анализаторы кода, похоже, проверяют это. Я забыл, какие именно.