Подтвердить что ты не робот

Как правильно использовать директиву #include?

Есть ли какой-либо материал о том, как правильно использовать #include? Я не нашел текстового текста на C/С++, который подробно объясняет это использование. В формальном проекте я всегда путаюсь с этим.

4b9b3361

Ответ 1

  • Проверьте крупномасштабный дизайн программного обеспечения на С++ от Джона Лакоса, если у вас есть деньги.
  • В руководстве по кодированию Google С++ также есть некоторые вещи OK.
  • Проверьте материалы Sutter Herb онлайн (блог).

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

Ответ 2

Большая, которая всегда сбивала меня с толку, такова:

Выполняется поиск в пути заголовка:

#include <stdio.h>

Выполняется поиск в вашем локальном каталоге:

#include "myfile.h"

Вторая вещь, которую вы должны делать с КАЖДОМ заголовком, такова:

myfilename.h:

#ifndef MYFILENAME_H
#define MYFILENAME_H
//put code here
#endif

Этот шаблон означает, что вы не можете упасть на переопределение заголовков в своей компиляции (приветствия orsogufo для указания на меня, это называется "включить охрану" ). Прочитайте, как компилятор C на самом деле компилирует файлы (перед связыванием), потому что это сделает мир #define и #include очень полезным для вас, компилятор C, когда дело доходит до разбора текста, не очень умный. (Сам компилятор C - это другое дело)

Ответ 3

Таким образом, ваш компилятор может поддерживать 2 уникальных пути поиска для включенных файлов:
Неформально мы могли бы назвать систему include path и указать путь пользователя.
#include <XX> выполняет поиск в системе, включая путь.
#include "XX" ищет путь включения пользователя, затем система включает путь.

Проверка черновика стандарта n2521:
Раздел 16.2:

2 A preprocessing directive of the form 

  # include < h-char-sequence> new-line 

  searches a sequence of implementation-defined places for a header identified
  uniquely by the specified sequence between the < and > delimiters, and
  causes the replacement of that directive by the entire contents of the
  header. How the places are specified or the header identified is
  implementation-defined. 

3 A preprocessing directive of the form 

  # include " q-char-sequence" new-line 

  causes the replacement of that directive by the entire contents of the
  source file identified by the specified sequence between the " " delimiters.
  The named source file is searched for in an implementation-defined manner.
  If this search is not supported, or if the search fails, the directive is
  reprocessed as if it read

  # include < h-char-sequence> new-line 

  with the identical contained sequence (including > characters, if any)
  from the original directive. 

Примером этого может быть gcc

  -isystem <dir>              Add <dir> to the start of the system include path
  -idirafter <dir>            Add <dir> to the end of the system include path
  -iwithprefix <dir>          Add <dir> to the end of the system include path
  -iquote <dir>               Add <dir> to the end of the quote include path
  -iwithprefixbefore <dir>    Add <dir> to the end of the main include path
  -I <dir>                    Add <dir> to the end of the main include path

Чтобы узнать, где находится ваш gcc, выполните следующие действия:

g++ -v -E -xc++ /dev/null -I LOOK_IN_HERE
#include "..." search starts here:
#include <...> search starts here:
  LOOK_IN_HERE
  /usr/include/c++/4.0.0
  /usr/include/c++/4.0.0/i686-apple-darwin9
  /usr/include/c++/4.0.0/backward
  /usr/local/include
  /usr/lib/gcc/i686-apple-darwin9/4.0.1/include
  /usr/include
  /System/Library/Frameworks (framework directory)
  /Library/Frameworks (framework directory)
End of search list.

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

Пример

Файл: plop.cpp

#include "plop.h"
#include "plop-used-class.h"

/// C Header Files
#include <stdio.h>    // I know bad example but I drew a blank

/// C++ Header files
#include <vector>
#include <memory>

Таким образом, если заголовочный файл "plop-used-class.h" должен включать <vector> это будет рассмотрено компилятором. Если бы я положил <vector> наверху эта ошибка была бы скрыта от компилятора.

Ответ 4

В дополнение к другим комментариям помните, что вам не нужно # включать заголовок в другой заголовок, если у вас есть только указатель или ссылка. Например:.

Требуется заголовок:

#include "Y.h"
class X
{
   Y y; // need header for Y
};

Заголовок не требуется:

class Y; 
class X
{
   Y* y; // don't need header for Y
};
//#include "Y.h" in .cpp file

Второй пример быстрее компилируется и имеет меньше зависимостей. Это может быть важно в больших базовых кодах.

Ответ 5

Заголовочные файлы - это способ разделения интерфейса и реализации. Они делятся на два типа: стандартные и пользовательские файлы заголовков. Стандартный файл заголовка, например string.h, позволяет нам получить доступ к функциям базовой библиотеки C. Вы должны # включить его в каждый .c файл, который использует соответствующую функциональность. Обычно это использует скобки, как в #include Пользовательский заголовочный файл предоставляет вашу реализацию функций другим программистам или другим частям вашего кода C. Если для вычислений с рациональными числами был реализован модуль, называемый rational.c, он должен иметь соответствующий файл rational.h для своего публичного интерфейса. Каждый файл, который использует функциональные возможности, должен #include rational.h, а также rational.c должен # включать его. Обычно это делается с помощью #include "rational.h" Часть компиляции, которая делает #includes, называется препроцессором C. В основном это текстовые замены и пасты. Spence верна в своем шаблоне для предотвращения дублирования #includes, которые испортили пространство имен. Это основа включения, GNU Make дает вам больше мощности, а также больше проблем.

Ответ 6

Просто добавление к Andy Brice отвечает, вы также можете обойтись с объявлениями вперед для возвращаемых значений функции:

class Question;
class Answer;

class UniversityChallenge
{
...
    Answer AskQuestion( Question* );
...
};

Здесь ссылка на вопрос, который я задал некоторое время назад с хорошими ответами http://bytes.com/groups/c/606466-forward-declaration-allowed.

Ответ 7

Отъезд обсуждение по использованию #include<filename.h> и #include<filename> для С++ включает библиотеки C.

Ответ 8

Вы используете #include "yourfile.h", если yourfile.h находится в текущем рабочем каталоге и #include <yourfile.h>, если путь к файлу yourfile.h был включен в каталоги включений С++ (где-то в конфигурации, например: c:\mylib\yourfile.h, путь c:\mylib\ должен быть указан как каталог include) Также вы можете включить .cpp и .hpp(h plus plus). Существует определенный набор файлов, которые можно записать так: #include <iostream>. Для этой конкретной работы вам нужно указать using namespace std;

Существует очень приятное программное обеспечение, которое интегрировано с визуальным С++ для Microsoft и показывает пути включения. http://www.profactor.co.uk/includemanager.php

Ответ 9

Редактировать: Энди Брайс также сделал этот шаг более кратким способом.

Следуя за нулевым ответом, самое важное, о чем нужно подумать, - это разместить свой # include.

Когда вы пишете #include, препроцессор буквально включает в себя содержимое файла, который вы перечисляете в текущем файле, включая любые #includes в этих файлах. Это может привести к очень большим файлам во время компиляции (coad bloat), поэтому вам нужно внимательно изучить, если требуется #include.

В стандартном макете кодового файла, где у вас есть .h файл для класса с объявлениями класса и функции, а затем файл реализации .cpp, вы должны быть осторожны с количеством #includes, которые входят в заголовок файл. Это связано с тем, что каждый раз, когда вы вносите изменения в заголовочный файл, все файлы, которые также включают его (то есть, которые используют ваш класс), также должны быть перекомпилированы; если в самом заголовке есть много включений, то каждый файл, который использует класс, значительно раздувается во время компиляции.

Лучше использовать, если это возможно, форвардные объявления, чтобы вы могли писать сигнатуры методов и т.д., а затем # включать соответствующие файлы в .cpp файл, чтобы вы могли фактически использовать классы и структуры, зависящие от вашего кода на.

//In myclass.h
class UtilClass; //Forward declaration of UtilClass - avoids having to #include untilclass.h here

class MyClass
{
    MyClass();
    ~MyClass();

    void DoSomethingWithUtils(UtilClass *util); //This will compile due to forward declaration above
};

//Then in the .cpp
#include utilclass.h

void MyClass::DoSomethingWithUtils(UtilClass *util)
{
    util->DoSomething(); //This will compile, because the class definition is included locally in this .cpp file.
}