У Java-программиста есть вопросы относительно файлов заголовков C - PullRequest
1 голос
/ 24 августа 2009

У меня довольно много практики с Java в качестве языка программирования, но я совершенно новичок в C. Я понимаю, что заголовочный файл содержит предварительные объявления для методов и переменных. Чем это отличается от абстрактного класса в Java?

Ответы [ 8 ]

6 голосов
/ 24 августа 2009

Краткий ответ:

Абстрактные классы - это концепция объектно-ориентированного программирования. Заголовочные файлы являются необходимостью из-за способа, которым построен язык C. Это никак нельзя сравнить

Длинный ответ

Чтобы понять заголовочный файл и необходимость в заголовочных файлах, вы должны понимать понятия «объявление» и «определение». В C и C ++ объявление означает, что вы объявляете, что где-то что-то существует, например, функция.

void Test(int i);

Теперь мы объявили, что где-то в программе существует функция Test, которая принимает один параметр int. Когда у вас есть определение, вы определяете, что это такое:

void Test(int i)
{
    ...
}

Здесь мы определили, что такое функция void Test (int).

Глобальные переменные объявляются с использованием ключевого слова extern

extern int i;

Они определены без ключевого слова extern

int i;

Когда вы компилируете программу на C, вы компилируете каждый исходный файл (файл .c) в файл .obj. Определения будут скомпилированы в файл .obj как фактический код. Когда все они скомпилированы, они связаны с конечным исполняемым файлом. Следовательно, функция должна быть определена только в одном файле .c, в противном случае одна и та же функция будет несколько раз выполняться в исполняемом файле. Это не очень важно, если определения функций идентичны. Более проблематично, если глобальная переменная дважды связана с одним и тем же исполняемым файлом. Это оставит половину кода для использования одного экземпляра, а другую половину кода для использования другого экземпляра.

Но функции, определенные в одном файле .c, не могут видеть функции, определенные в других файлах .c. Поэтому, если из файла file1.c вам нужен доступ к функции Test (int), определенной в file2.c, вам необходимо иметь объявление Test (int), присутствующее при компиляции file1.c. Когда file1.c скомпилирован в file1.obj, результирующий файл .obj будет содержать информацию о том, что ему нужно где-то определить Test (int). Когда программа связана, компоновщик идентифицирует, что file2.obj содержит функцию, от которой зависит file1.obj. Если нет файла .obj, содержащего определение для этой функции, вы получите ошибку компоновщика, а не ошибку компилятора (ошибки компоновщика значительно сложнее найти и исправить ошибки компилятора, потому что вы не получите имя файла и номер строки для полученного файл)

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

4 голосов
/ 24 августа 2009
  1. IMO, это в основном потому, что многие программисты на Си, похоже, думают, что Java-программисты не знают, как программировать «по-настоящему», например обработка указателей, памяти и т. д.

  2. Я бы лучше сравнил заголовки с интерфейсами Java, в том смысле, что они обычно определяют, как должен использоваться API. Заголовки - это просто способ избежать вставки копий: препроцессор просто включает содержимое заголовка в исходный файл, когда встречает директиву #include. Вы помещаете в заголовок каждое объявление, которое пользователь обычно использует.

3 голосов
/ 24 августа 2009

Вот ответы:

  1. Java имеет плохую репутацию среди некоторых хардкорных программистов на C, в основном потому, что они думают:

    • это "слишком просто" (без управления памятью, segfaults)
    • "нельзя использовать для серьезной работы"
    • "только для Интернета" или
    • "медленный".

    Java - едва ли самый простой язык в мире в наши дни по сравнению с некоторыми языками, такими как Python и т. Д.

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

  2. Когда вы работаете в C, нет абстрактных классов.

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

    Хотя вы можете как бы использовать концепции ОО в С, в нем нет встроенной поддержки классов и аналогичных основ ОО. Практически невозможно реализовать наследование в простом C, поэтому на самом деле никогда не может иметь ОО или абстрактные классы в этом отношении. Я бы предложил придерживаться простых старых struct с.

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

    Я не уверен, есть ли в Java их, но я думаю, что более близким аналогом могут быть частичные классы в C #.

2 голосов
/ 24 августа 2009

Комплексное чтение: Обучение C на Java Рекомендуемое чтение для разработчиков, которые переходят с Java на C.

2 голосов
/ 24 августа 2009

Если вы хотите что-то объявить, вы должны фактически доставить и реализовать это, иначе компилятор будет жаловаться. Заголовок позволяет отображать открытый API «модуля» и делать объявления доступными (для проверки типов и т. Д.) Для других частей программы.

1 голос
/ 24 августа 2009
  1. Программы на C запускаются напрямую, в то время как программы на Java работают внутри JVM, поэтому распространено мнение, что программы на Java работают медленно.Также в Java вы скрыты от некоторых низкоуровневых конструкций (указатель, прямой доступ к памяти), управления памятью и т. Д. *

  2. В Си объявление и определение функции разделены.Объявление «объявляет», что существует функция, которая вызывается этими аргументами и возвращает что-то.Определение «определяет», что на самом деле делает функция.Первое делается в заголовочных файлах, последнее - в реальном коде.Когда вы компилируете свой код, вы должны использовать заголовочные файлы, чтобы сообщить компилятору о наличии такой функции, и ссылку в двоичном коде, который содержит двоичный код функции.

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

1 голос
/ 24 августа 2009

Хотя ваш первый вопрос мне кажется субъективным, я отвечу на второй:

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

Типичный шаблон: вы распространяете файлы заголовков для вашей библиотеки и dll (например), которая содержит объектный код. Затем в ваше приложение вы включаете заголовок, и компилятор сможет его скомпилировать, поскольку он найдет объявление в заголовке. Не нужно предоставлять фактическую реализацию кода, которая будет доступна для компоновщика через dll.

1 голос
/ 24 августа 2009
  1. Я думаю, что в Java есть много насмешек (насмешек, смеха, презрения, насмешек) просто потому, что она популярна.

  2. Абстрактные классы и интерфейсы определяют контракт или набор функций, которые могут быть вызваны для объекта определенного типа. Прототипы функций в Си действительно только проверяют время проверки типов аргументов функций / возвращаемых значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...