Как включить файлы заголовков

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

#include <stdlib.h>
#include "Some_Header.h"

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

Другой вопрос: (откуда я здесь), как мне получить доступ к классу за пределами файла, в котором он был определен? Скажем, у меня есть one.cpp и two.cpp.

В one.cpp:

class Something {
    ...

В файле two.cpp:

class SomethingElse {
    Something *example;
    ...

Как это? В Java вы просто предварите имя класса с помощью "public". В С++, конфликтующие классы кажутся немного более трудными.

Ответ 1

Угловые скобки в директивах #include означает, что путь поиска ограничивается каталогом "system" include. Двойные кавычки означают, что путь поиска включает текущий каталог, за которым следуют каталоги системы.

Случай с именем файла имеет значение, когда ваша ОС использует файловую систему, чувствительную к регистру. Похоже, что вы можете использовать Windows или Mac OS X, где имена файлов по умолчанию нечувствительны к регистру.

Ответ 2

Угловые скобки ищут заголовок в каталогах системных заголовков (например, /usr/include). Котировки - это просто абсолютный или относительный путь, например /path/to/header.h или ../headers/abc.h.

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

Ответ 3

Вопрос 1

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

Это не имеет значения, но обычная практика:

  • Используйте угловые скобки для системы заголовки.
  • Пользовательские двойные кавычки для пользователя определенные заголовки (ваши собственные заголовки)

Вопросы 2 и 3

Другой вопрос: (из Java здесь), как мне получить доступ к классу за пределами файл был определен в?

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

//One.h
#ifndef ONE_H
#define ONE_H
class Something
{
public:
    void doSomething(){}

};
#endif

//Two.cpp
#include "One.h"
class SomethingElse
{
   SomeThing *example;
};

Ответ 4

Сначала прост вопрос:

Имеет ли значение, если они капитализируются определенным образом?

В большинстве случаев includes относятся к файлам, а компилятор должен иметь возможность находить файл, который вы включаете в систему. По этой причине капитализация имеет значение во всех системах, где файловая система чувствительна к регистру. Если вы хотите сохранить минимальную переносимость, вы должны быть согласованы в имени файлов и include. (Все linux и mac os по умолчанию имеют файловые системы, чувствительные к регистру, в Windows вы также можете настроить NTFS как чувствительность к регистру)

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

Насколько важно импортировать файлы заголовков?

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

#include <x.h> // search in order in set1 of directories
#include "x.h" // search in order in set2 of directories
               // if search fails, search also in set1

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

Возвращаясь к реальному миру, большинство компиляторов будет включать только текущий каталог в set2, причем set1 - это все системы, включающие в себя местоположения (которые обычно могут быть расширены с помощью аргументов компилятора). В этих случаях, если файл присутствует только в текущий каталог, #include "a.h" найдет его, но #include <a.h> не будет.

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

Наконец, хотя никакой компилятор, о котором я его знаю, не делает этого, стандарт позволяет реализации (компилятору) не создавать стандартные заголовки в качестве реальных файлов, а обрабатывать включение стандартных заголовков внутри. Это единственный случай, когда теоретически #include "vector" может не включать определения класса std::vector (или любого другого стандартного заголовка). Но это не практическая проблема, и я не думаю, что это когда-либо будет.

Ответ 5

Во-первых, #include является предпроцессорной директивой C и не является строго частью языка С++ как таковой. Вы можете узнать больше об этом здесь, хотя это специально для препроцессора GNU C, поэтому может отличаться от того, что вы используете. Я думаю, вы всегда должны учитывать чувствительность к регистру в include файлах. Не делать этого может затруднить перенос кода на чувствительную к регистру ОС, такую ​​как UNIX.

Использование "или < > является довольно тонким, как объяснялось выше, и в большинстве случаев вы не заметите никакой разницы. Использование" " обычно сначала ищет текущий каталог. Я склонен не использовать это как:

  • Я знаю, где мои заголовки - я всегда указываю их с -I на линии компиляции.
  • Я был пойман раньше, когда локальная копия заголовка перекрыла центральную копию, которую я надеялся подобрать.

Я также заметил некоторые побочные эффекты, например, при использовании make для создания деревьев зависимостей (я не могу полностью вспомнить проблему - он рассматривал разные варианты, по-разному, следуя некоторым, а не другим, но это было около 7 лет назад)

Во-вторых, на ваш вопрос о том, как ссылаться на функции в других файлах, отвечает here/