Заголовки #include в C/C++

После чтения нескольких вопросов относительно проблем с компиляцией (особенно C++) и замечающий, что во многих случаях проблемой является недостающий заголовок #include. Я не мог помочь задаться вопросом в своем незнании и спросить меня (и теперь Вам):

Почему недостающие заголовки автоматически не проверяют и добавляют или требуют программисту?

Такая функция доступна для операторов импорта Java в Netbeans, например.

6
задан Carlos 22 March 2010 в 14:48
поделиться

9 ответов

Помните конфликт в Java между java.util.Date и java.sql.Date ? Если кто-то использует в своем коде Date , вы не сможете сказать, забыли ли они import java.util.Date или import java.sql.Date .

И в Java, и в C ++ невозможно с уверенностью сказать, какой оператор импорта / включения отсутствует. Так что ни один язык не пытается. Ваша IDE может предлагать необъявленные символы, используемые в вашем коде.

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

Как правило, в среде C ++ IDE невозможно определить, является ли зависимость заголовка «гарантированной» или это просто случайная деталь реализации, на которую пользователям не следует полагаться. Очевидно, что для стандартных библиотек он может просто знать, что определено в каких заголовках, но как только вы перейдете к сторонним библиотекам, это станет довольно неопределенным.

Я думаю, что большинство программистов на C ++ ожидают, что им придется искать, какие заголовки и какие символы определяют. В Java правило «один открытый класс для каждого файла» значительно упрощает это, и вы просто импортируете нужные пакеты / классы. В C ++ нет пакетов, и для среды IDE единственный способ найти класс с именем my_namespace :: something :: MyClass - это искать его в каждом файле заголовка.

12
ответ дан 8 December 2019 в 03:26
поделиться

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

В C или C ++ имя, которое вы даете заголовку, вовсе не обязательно должно совпадать с содержимым. Если вы очень хотите, вы можете назвать свои заголовки 1.h, 2.h, 3.h и так далее - или даже 1.bas, 2.pas, 3.java, 4.ada и т. Д. вводящие в заблуждение имена, которые вы предпочитаете. Очевидно, это плохая идея, но если бы вы все равно это сделали, компилятор бы это не беспокоило.

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

1
ответ дан 8 December 2019 в 03:26
поделиться

Поскольку в тот момент, когда вы доверяете компьютеру думать за вас, у вас на руках оказывается серьезный случай SkyNet.

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

2
ответ дан 8 December 2019 в 03:26
поделиться

NetBeans - это IDE (интегрированная среда разработки). Некоторые IDE C / C ++ имеют эту функцию ... но не все знают об этом или используют ее.

0
ответ дан 8 December 2019 в 03:26
поделиться

Почему отсутствующие заголовки не проверяются автоматически и не добавляются или не запрашиваются программистом?

Но они автоматически проверяются.

  1. Мой компилятор не может компилировать, когда не может найти заголовок.
  2. Моя IDE (eclipse) добавляет визуальную подсказку, когда не может найти файл заголовка, который я #include, он подчеркивает строку #include и предоставляет всплывающую подсказку, сообщающую мне, в чем проблема.

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

7
ответ дан 8 December 2019 в 03:26
поделиться

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

1
ответ дан 8 December 2019 в 03:26
поделиться

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

0
ответ дан 8 December 2019 в 03:26
поделиться

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

В отличие от Java, C ++ не считает какие-либо файлы «особенными». В Java есть гигантская (раздутая) библиотека классов, которая автоматически становится доступной для программиста.

В C ++ такой концепции не существует. Вы указываете компилятору, по каким путям искать, и всякий раз, когда вы #include файл, он будет искать имя файла в этих путях.

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

Компилятор не знает , что sqrt определен в заголовке math.h . Или что он также обычно определяется в cmath На самом деле функции, определенные заголовком, могут различаться . Возможно, если я # определю соответствующий символ препроцессора, некоторые функции будут удалены из определенного заголовка, а другие будут включены.

Но в отличие от Java, где функции и классы, определенные библиотекой, можно определить, просто изучив метаданные файла библиотеки, в C ++ заголовок должен быть скомпилирован. И результат его компиляции может варьироваться в зависимости от контекста, в который он включен.

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

2
ответ дан 8 December 2019 в 03:26
поделиться

Насколько я помню, Java также выбрасывает ошибку, если пропущен оператор Import. Это графический интерфейс NetBeans, который облегчает вам жизнь.

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

4
ответ дан 8 December 2019 в 03:26
поделиться