Перейти к содержимому

Как подключить заголовочный файл в c visual studio

  • автор:

Файлы заголовков (C++)

Имена элементов программы, таких как переменные, функции, классы и т. д., должны быть объявлены до их использования. Например, вы не можете просто написать x = 42 без первого объявления «x».

int x; // declaration x = 42; // use x 

Объявление сообщает компилятору, является int ли элемент , функцией double , или class другой вещью. Кроме того, каждое имя должно быть объявлено (прямо или косвенно) в каждом CPP-файле, в котором он используется. При компиляции программы каждый CPP-файл компилируется независимо в единицу компиляции. Компилятор не знает, какие имена объявляются в других единицах компиляции. Это означает, что если вы определяете класс или функцию или глобальную переменную, необходимо указать объявление этой вещи в каждом дополнительном CPP-файле, который использует его. Каждое объявление этой вещи должно быть точно идентичным во всех файлах. Небольшое несоответствие приведет к ошибкам или непреднамеренное поведение, когда компоновщик пытается объединить все единицы компиляции в одну программу.

Чтобы свести к минимуму потенциал ошибок, C++ принял соглашение об использовании файлов заголовков для хранения объявлений. Вы делаете объявления в файле заголовка, а затем используйте директиву #include в каждом CPP-файле или другом файле заголовка, который требует этого объявления. Директива #include вставляет копию файла заголовка непосредственно в CPP-файл перед компиляцией.

В Visual Studio 2019 функция модулей C++20 представлена в качестве улучшения и окончательной замены файлов заголовков . Дополнительные сведения см. в разделе «Общие сведения о модулях в C++».

Пример

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

// my_class.h namespace N < class my_class < public: void do_something(); >; > 

Затем создайте файл реализации (обычно с расширением CPP или аналогичного расширения). Мы вызовем файл my_class.cpp и предоставим определение для объявления члена. Мы добавим директиву #include для файла «my_class.h», чтобы объявление my_class вставлялось в этот момент в CPP-файле, и мы включаем в объявление. std::cout Обратите внимание, что кавычки используются для файлов заголовков в том же каталоге, что и исходный файл, а для заголовков стандартной библиотеки используются угловые скобки. Кроме того, многие заголовки стандартной библиотеки не имеют расширения H или других файлов.

В файле реализации можно использовать using инструкцию, чтобы избежать необходимости квалифицировать каждую упоминание «my_class» или «cout» с «N::» или «std::». Не помещайте using инструкции в файлы заголовков!

// my_class.cpp #include "my_class.h" // header in local directory #include // header in standard library using namespace N; using namespace std; void my_class::do_something()

Теперь мы можем использовать my_class в другом CPP-файле. Мы #include файл заголовка, чтобы компилятор извлекал объявление. Все, что компилятор должен знать, является то, что my_class является классом, который имеет общедоступную do_something() функцию-член.

// my_program.cpp #include "my_class.h" using namespace N; int main()

После завершения компиляции каждого CPP-файла в OBJ-файлы он передает OBJ-файлы компоновщику. При слиянии компоновщика файлов объектов он находит точно одно определение для my_class; он находится в OBJ-файле, создаваемом для my_class.cpp, и сборка завершается успешно.

Включение охранников

Как правило, файлы заголовков имеют параметр include guard или директиву #pragma once , чтобы убедиться, что они не вставляются несколько раз в один CPP-файл.

// my_class.h #ifndef MY_CLASS_H // include guard #define MY_CLASS_H namespace N < class my_class < public: void do_something(); >; > #endif /* MY_CLASS_H */ 

Что нужно поместить в файл заголовка

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

  • встроенные определения типов в пространстве имен или глобальных область
  • определения функций, отличных от встроенных
  • Определения переменных, отличные от const
  • агрегатные определения
  • безымянные пространства имен
  • Директивы using

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

Пример файла заголовка

В следующем примере показаны различные виды объявлений и определений, которые разрешены в файле заголовка:

// sample.h #pragma once #include // #include directive #include namespace N // namespace declaration < inline namespace P < //. >enum class colors : short < red, blue, purple, azure >; const double PI = 3.14; // const and constexpr definitions constexpr int MeaningOfLife< 42 >; constexpr int get_meaning() < static_assert(MeaningOfLife == 42, "unexpected!"); // static_assert return MeaningOfLife; >using vstr = std::vector; // type alias extern double d; // extern variable #define LOG // macro definition #ifdef LOG // conditional compilation directive void print_to_log(); #endif class my_class // regular class definition, < // but no non-inline function definitions friend class other_class; public: void do_something(); // definition in my_class.cpp inline void put_value(int i) < vals.push_back(i); >// inline OK private: vstr vals; int i; >; struct RGB < short r< 0 >; // member initialization short g< 0 >; short b< 0 >; >; template // template definition class value_store < public: value_store() = default; void write_value(T val) < //. function definition OK in template >private: std::vector vals; >; template // template declaration class value_widget; > 

Подключение собственного заголовочного файла

Author24 — интернет-сервис помощи студентам

В общем есть файл с исходный кодом, который содержит main(). Здесь же подключаю свой заголовочный файл, который тянет за собой другой файл исходный код с функцией. Собственно, в чем загвоздка, когда подключаю просто #include «median.h» то компилятор (Visual studio 2010) не видит файл, хотя все лежит вместе в папке проекта. Если прописывать полный путь, то все компилируется. Я конечно подозреваю что, возможно, нужно указать компилятору где искать файлы по умолчанию, но как это сделать? У кого какие идеи?

Здесь вы можете заказать любую студенческую или школьную работу.

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Подключение заголовочного файла
При подключении заголовочного файла вылазит ошибка: Код: #include "stdafx.h" #include.

Подключение заголовочного файла
Как подключить правильно заголовочный файл и какие библиотеки подключать в заголовочном файле?

Создание и подключение заголовочного файла
Всем привет! Столкнулся с простой но очень интересной проблемой. Создаю новый проект в MVS2012.

Подключение заголовочного файла QList
Что-то затупил по структуре проекта. есть header.h: #include <QList> . //код Подключаем.

130 / 25 / 12
Регистрация: 12.08.2015
Сообщений: 221

Для того, что бы компилятор видел заголовочный файл, он должен быть включен в дерево проекта, в папку Заголовочные файлы. Дерево проекта находится слева в рабочей среде MS Visual Studio. Для добавления заголовочного файла, нажми правой кнопкой мыши на дереве и нажми «добавить новый элемент». Там ищешь файл .h, именуешь его и вставляешь.

#Инклад твоего собственного .h файла должен производиться таким образом:

#include "my_functions.h"

И ни в коем случае не так.

1 2 3
#include //или #include

Ибо не найдет! И не должен в принципе.

Как подключать к хедеру другие .cpp файлы, ты знаешь, я надеюсь. (надо указать прототип функций в файле .h)

Кстати, в .cpp файле с функцией тоже должен быть #include с названием хедера.

4059 / 3313 / 924
Регистрация: 25.03.2012
Сообщений: 12,464
Записей в блоге: 1

colonialist, надеюсь ты знаешь, что твоя функция должна находиться в cpp файле, а не в хедере. И то что срр файл инклудиться не должен.

Регистрация: 21.08.2015
Сообщений: 5

Вобщем да, забыл оговориться, делал подключения файлов все как по книге, в том то и загвоздка, что все вроде бы правильно, и отдельно заголовочные файлы .h с объявлением функций, отдельно .cpp с их реализацией, все добавлено в проект как нужно, но именно в главном файле когда подключаю #include «median.h» компилятор его не видит, видит только если #include «C:\Users\AmerigoMan\Documents\visual studio 2010\Projects\LolTime\LolTime\grade.h» но так ведь не должно быть и выглядит глупо.
Собственно, для наглядности выкладываю скрины

Как подключить заголовочный файл в другой папке?

Вот такой вопрос, есть папка проекта в ней папка с исходным кодом и папка с заголовочными файлами, как мне подключить заголовочные файлы из их собственной папки? Дело в том, что когда я пытаюсь подключить заголовочные файлы, компилятор их не видит.
Выглядит это так:
\SDL2_Lessons\src — папка с исходниками
\SDL2_Lessons\src_h — папка с заголовочными список папок и файлов в папке проекта ошибка подключения

Отслеживать
задан 5 сен 2020 в 17:12
LinadVonapets LinadVonapets
41 1 1 серебряный знак 7 7 бронзовых знаков

А указать что-то типа #include «src_h/options.h» (обратите внимание на кавычки, кстати) религия не позволяет? 🙂

5 сен 2020 в 17:17
Это не сработало( Всё та же история
5 сен 2020 в 17:20

Ну значит #include «\SDL2_Lessons\src_h\options.h» — смотрите сами, что у вас в свойствах проекта указано, где искать заголовочные файлы.

5 сен 2020 в 17:22

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Если работаете в Visual Studio то нужно открыть свойства проекта, найти Configuration Properties->C/C++->General . Далее найти пункт Additional Include Directories В нем прописать путь до вашей папки где лежат ваши заголовочные файлы. Тогда вы сможете включать заголовочные файлы через угловые скобки #include

Либо можете не включать папку в Additional Include Directories , а указывать ваш файл относительно исходного файла, например #include «../Myheaders/myheader.h» Но тогда уже в обычных ковычках.

Отслеживать
ответ дан 5 сен 2020 в 17:38
Rikitikitavi Rikitikitavi
2,409 4 4 золотых знака 20 20 серебряных знаков 37 37 бронзовых знаков
Разве нельзя в этом случае включать, используя и кавычки, и угловые скобки (а не или)?
5 сен 2020 в 18:33

@dIm0n можно, но если использовать кавычки то сначала компилятор будет искать локально, и если не найдет то пойдет искать во включенных директориях, если использовать угловые то поиск будет осуществляться в глобальных по отношению к проекту папках. Подробнее ru.stackoverflow.com/a/150/210482

6 сен 2020 в 3:44

Скорее stackoverflow.com/q/21593/13970074. Но из ответа складывается впечатление, что можно одним способом, но нельзя другим

Как подключить заголовочный файл в c visual studio

Если проект содержит множество файлов, то может возникнуть ситуация, что один и тот же заголовочный файл будет подключен несколько раз. Однако на этапе компиляции это может привести к ошибкам. Например, пусть у нас есть заголовочный файл user.h со следующим кодом:

struct User < char* name; unsigned age; >; void printUser(struct User);

Здесь определена структура User и прототип функции printUser, которая должна выводить структуру User на консоль.

И также пусть будет файл user.c с определением функции printUser:

#include #include «user.h» void printUser(struct User user)

Также пусть у нас будет заголовочный файл userlist.h со следующим кодом:

#include // подключаем заголовочный файл, где определена структура User #include "user.h" // функция вывода массива структур User void printUserList(struct User*, size_t);

Здесь вначале подключается заголовочный файл «user.h», поскольку нам предстоит работать со структурами User, а потом определяется прототип функции printUserList для вывода массива структур User определенной длины на консоль.

В файле userlist.c реализуем функцию printUserList:

#include #include "userlist.h" void printUserList(struct User* users, size_t count) < for(size_t i=0; i < count; i++) < printUser(users[i]); >>

Данная реализация функции проходит по массиву users и для каждого его элемента вызывает функцию printUser, которая объявлена в подключенном файле «user.h».

И определим файл app.c , который будет представлять главный файл программы и будет использовать функцию printUserList для вывода массива структур User на консоль:

#include "userlist.h" // подключаем API модуля userlist #include "user.h" // подключаем API модуля user #define USERS_COUNT 4 int main(void) < struct User users[USERS_COUNT] = < , , , >; printUserList(users, USERS_COUNT); >

Таким образом, у нас определено 5 файлов:

  • user.h
  • user.c
  • userlist.h
  • userlist.c
  • app.c

Хотя у нас казалось бы довольно простая программа, где сложно допустить ошибку, но тем не менее на стадии компиляции мы получим ошибку

c:\C>gcc -Wall -pedantic app.c userlist.c user.c -o app & app In file included from app.c:3: user.h:1:8: error: redefinition of 'struct User' 1 | struct User | ^~~~ In file included from userlist.h:1, from app.c:2: user.h:1:8: note: originally defined here 1 | struct User | ^~~~ user.h:7:6: error: conflicting types for 'printUser'; have 'void(struct User)' 7 | void printUser(struct User); | ^~~~~~~~~ user.h:7:6: note: previous declaration of 'printUser' with type 'void(struct User)' 7 | void printUser(struct User);

Так по консольному выводу мы видим, что идет переопределение структуры User, кроме того, проблемы с функцией printUser.

И проблема в нашем случае состоит в том, что в файле app.c два раза подключается заголовочный файл user.h

#include "userlist.h" // подключаем API модуля userlist #include "user.h" // подключаем API модуля user

Ведь в файле userlist.h уже подключен файл «user.h». Поэтому заголовочные файлы следует подключать в программу только один раз. И чтобы выйти из этой ситуации, мы можем убрать подключение файла user.h :

#include "userlist.h" // подключаем API модулей userlist и user #define USERS_COUNT 4 int main(void) < struct User users[USERS_COUNT] = < , , , >; printUserList(users, USERS_COUNT); >

Теперь ошибки не будет. Однако в большой кодовой базе, где подключается куча заголовочных файлов бывает сложно уследить за всеми подключениями. И в этом случае для проверки подключения используют два способа: выражение #ifdef и директиву #pragma once

Использование директивы #pragma once может показаться наиболее простым способом, однако это выражение не определено в стандарте языка С, хотя и поддерживается многими препроцессорами языка С. Эта директива указывается в подключаемом заголовочном файле:

#pragma once // однократное подключение файла struct User < char* name; unsigned age; >; void printUser(struct User);

Минусом данного подхода является то, что можно наткнуться на компилятор, препроцессор которого не поддерживает данную директиву.

Другой подход представляет проверка определения константы с помощью директивы #ifndef в следующем виде:

#ifndef SOMECODE_H // если НЕ определена константа SOMECODE_H #define SOMECODE_H // определяем константу SOMECODE_H // здесь идет определение заголовочного файла #endif // завершение конструкции #ifndef

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

Если константа НЕ определена, определяем ее с помощью директивы #define и далее вплоть до выражения #ifdef помещаем содержимое заголовочного файла — определение структур, констант и прототипов функций.

Название проверяемой константы должно быть уникально на всем множестве файлов проекта. Поэтому обычно в качестве названия константы используется название подключаемого файла, где точка заменяется прочерком. Например, для файла user.h определяется константа user_h или USER_H . Бывают ситуации, особенно при подключении внешних заголовочных файлов, созданных другими разработчиками, что названия этих файлов дублируются. В этом случае можно в качестве названия констант можно генерировать уникальные значения UUID или использовать числовые метки времени.

Применение #ifndef в файле user.h :

#ifndef user_h // если user_h не определена #define user_h // определяем user_h struct User // и помещаем определение структуры User < char* name; unsigned age; >; void printUser(struct User); // и определение прототипа функиции #endif // конец конструкции ifndef

После этого мы можем многократно включать заголовочный файл в других файлах кода:

#include "userlist.h" // подключаем API модуля userlist #include "user.h" // подключаем API модуля user #include "user.h" // подключаем API модуля user #include "user.h" // подключаем API модуля user #define USERS_COUNT 4 int main(void) < struct User users[USERS_COUNT] = < , , , >; printUserList(users, USERS_COUNT); >

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *