При написании проектов в C ++ управление сегментацией файлов очень необходимо. Сегодня редактор Foxin Technology Channel предоставит вам подробное объяснение файлов заголовок и исходных файлов в C ++. Я надеюсь, что вам будет полезно изучить эти знания!
Подробное объяснение файлов заголовков и исходных файлов в C ++
1. Режим компиляции C ++
Как правило, в программе C ++ есть только два типа файлов - .cpp файл и .h File. Среди них файл .cpp называется исходным файлом C ++, и в него помещается исходный код C ++; в то время как файл .h называется файлом заголовка C ++, и в него помещается исходный код C ++.
Язык C ++ поддерживает «отдельный сборник». Другими словами, все содержимое программы можно разделить на разные части и размещать в разных файлах .CPP. Вещи в файле .cpp относительно независимы. При компиляции (компиляции) вам не нужно общаться с другими файлами. Вам нужно связать только с другими целевыми файлами после сбора его в целевой файл. Например, глобальная функция «void a () {}» определяется в файле A.CPP, и эту функцию необходимо вызвать в файле B.CPP. Несмотря на это, файлы A.CPP и B.CPP не должны знать существование друг друга, но могут компилировать их отдельно. После сбора их в целевой файл, свяжите их, и вся программа может быть запущена.
Как это достигается? С точки зрения написания программ, это очень просто. В файле b.cpp, прежде чем вызывать функцию «void a ()», объявите функцию «void a ();»; первый. Это потому, что компилятор будет генерировать таблицу символов при составлении B.CPP. Символы, такие как «void a ()», которые невозможно увидеть, будут храниться в этой таблице. При снова связывании компилятор будет искать определение этого символа в других файлах объектов. После того, как программа может быть получена плавно.
Обратите внимание, что здесь упоминаются две концепции, одна - «определение», а другая - «объявление». Проще говоря, «Определение» означает, что описание символа полным и полным образом: является ли это переменной или функцией, какой тип он возвращает, какие параметры ему нужны, и т. Д. ». Объявление» просто заявляет о существовании этого символа, то есть говорит компилятору, что этот символ определяется в других файлах. Я буду использовать его в первую очередь. Когда вы ссылаетесь, перейдите в другое место, чтобы узнать, что это такое. При определении вы должны определить символ (переменная или функция) полностью в соответствии с синтаксисом C ++, и при объявлении вам нужно только написать прототип этого символа. Следует отметить, что символ может быть объявлен несколько раз по всей программе, но должен определяться только один раз. Представьте себе, что есть два разных определения символа, кто должен слушать компилятор?
Этот механизм приносит много преимуществ программистам C ++, а также приводит к методу написания программ. Считайте, что если есть очень часто используемая функция «void f () {}», которая будет вызвана во многих файлах .cpp во всей программе, тогда нам нужно определить эту функцию только в одном файле и объявить эту функцию в других файлах. С функцией легко справиться, и это означает только одно предложение, чтобы объявить его. Однако что, если есть слишком много функций, таких как куча математических функций, их сотни? Может ли каждый программист обязательно записать и записать все функции в форме их?
2. Что такое файл заголовка
Очевидно, ответ невозможно. Но есть очень простой способ помочь программистам сохранить проблему запоминания так много прототипов функций: сначала мы можем написать все заявления о объявлениях сотен функций и поместить их в файл. Когда программист нуждается в них, скопируйте все эти вещи в его исходный код.
Этот метод, безусловно, осуществим, но он все еще слишком хлопот и кажется неуклюжим. Таким образом, файл заголовка может сыграть свою роль. Так называемый файл заголовка на самом деле имеет тот же содержимое, что и контент в файле .cpp, оба из которых являются исходным кодом C ++. Но файл заголовка не должен быть скомпилирован. Мы помещаем все объявления функций в файл заголовка. Когда им нужен исходный файл .cpp, он может быть включен в этот файл .cpp через команду Macro «#include», чтобы их содержимое объединилось в файл .cpp. Когда файл .cpp составлен, воспроизводится функции их включенных файлов .h.
Давайте приведем пример. Предположим, что все математические функции имеют только два: F1 и F2, затем мы размещаем их определения в math.cpp:
/ * math.cpp */double f1 () {// сделай что -нибудь здесь ... return;} double f2 (двойной a) {// что -то здесь ... вернуть a * a;}/ * end of math.cpp *//И поместите объявление о функциях «эти» в файле заголовка Math.h:
/ * math.h */double f1 (); double f2 (Double);/ * end of Math.h */
В другом файле main.cpp я хочу вызвать эти две функции, поэтому мне просто нужно включить файл заголовка:
/ * main.cpp */#включить "math.h" main () {int number1 = f1 (); int number2 = f2 (number1);}/ * end of main.cpp */Это полная программа. Следует отметить, что файло. main.cpp и math.cpp могут быть скомпилированы для создания main.o и math.o соответственно, а затем связать эти два объектных файла, и программа может быть запущена.
3. #include
#include - это команда макроса из языка C, которая работает до компилятора, то есть в предварительном сборе. Цель #include - полностью и полностью включить содержимое файла, написанного после него в текущий файл. Стоит отметить, что у него нет других функций или подфункций. Его функция состоит в том, чтобы заменить каждое место, которое появляется на содержание файла, который он пишет за ним. Простая замена текста, больше ничего. Следовательно, первое предложение в файле main.cpp (#include "math.h") будет заменено на содержимое файла math.h до компиляции. То есть, когда процесс компиляции собирается начать, содержание Main.cpp изменилось:
/ * ~ main.cpp */double f1 (); double f2 (Double); main () {int number1 = f1 (); int number2 = f2 (number1);}/ * конец ~ main.cpp */Не более или менее, просто правильно. Точно так же, если мы используем функции F1 и F2 в дополнение к main.cpp, нам нужно только написать предложение #include "math.h", прежде чем использовать эти две функции.
4. Что должно быть записано в файле заголовка
Благодаря вышеуказанному обсуждению мы можем понять, что функция файла заголовка должна быть включена в другие .CPP. Они сами не участвуют в компиляции, но на самом деле их содержимое составлено в нескольких файлах .cpp. Благодаря правилу «определения может быть только один раз», мы можем легко сделать вывод, что объявления только переменные и функции должны быть размещены в файле заголовка, и их определения не должны быть размещены. Поскольку содержимое файла заголовка действительно будет введено в несколько разных файлов .cpp, и все они будут составлены. Конечно, можно поставить декларацию. Если вы разместите определение, оно эквивалентно определению символа (переменная или функция), появляющегося в нескольких файлах. Несмотря на то, что эти определения одинаковы, компилятор не является законным.
Следовательно, одна вещь, которую вы должны помнить, это то, что в файле заголовка .h могут быть только объявления переменных или функций, и не размещать определения. То есть предложения, такие как: extern int a; и void f (); может быть записано только в файле заголовка. Это заявления. Если вы напишете предложение как int a; или void f () {}, затем, как только файл заголовка включен в два или более файла .cpp, компилятор немедленно сообщит об ошибке. (О внешней части, это обсуждалось ранее, и разница между определением и объявлением здесь не будет обсуждаться.) Однако есть три исключения из этого правила.
1. Определение объекта Const может быть записано в файле заголовка. Поскольку глобальный объект Const не объявляется Extern по умолчанию, он действителен только в текущем файле. Запишите такой объект в файл заголовка, даже если он включен в множество других файлов .cpp, объект действителен только в файле, содержащем его и невидим для других файлов, поэтому он не приведет к нескольким определениям. В то же время, поскольку объекты в этих файлах .cpp включены из файла заголовка, это гарантирует, что значения объектов Const в этих файлах .cpp одинаковы, что можно сказать, что убивает двух птиц одним камнем. Точно так же определение статического объекта также может быть помещено в файл заголовка.
2. Определение встроенных функций может быть записано в файле заголовка. Поскольку встроенная функция требует, чтобы компилятор был вставлен в соответствии с его определением, когда она встречается с ней, а не просто обычная функция, которая может быть объявлена сначала, а затем связана (встроенные функции не будут связаны), компилятор должен увидеть полное определение встроенной функции во время компиляции. Если встроенная функция может быть определена только один раз как обычная функция, это будет трудно сделать. Поскольку в файле все в порядке, я могу написать определение встроенной функции в начале, чтобы я мог видеть определение, когда я использую его позже; Но что, если я использую эту функцию в других файлах? В этом нет почти хорошего решения, поэтому C ++ предусматривает, что в программу можно определить встроенные функции несколько раз. Пока встроенная функция появляется только один раз в файле .cpp, и во всех файлах. Затем, очевидно, очень разумно помещать определение встроенных функций в файл заголовка.
3. Определение класса может быть записано в файле заголовка. Потому что при создании объекта класса в программе компилятор может знать, как объект этого класса должен быть изложен только тогда, когда определение этого класса полностью видно, поэтому требования к определению класса в основном такие же, как встроенные функции. Следовательно, это хорошая практика, чтобы поместить определение класса в файл заголовка и включить файл заголовка в файл .cpp, используемый в этом классе. Здесь стоит отметить, что определение класса содержит членов данных и функционированных членов. Участники данных не будут определены до тех пор, пока не будет создан конкретный объект (выделенное пространство), но функциональные элементы должны быть определены с самого начала, что мы обычно называем реализацией класса. Как правило, наш подход состоит в том, чтобы поместить определение класса в файл заголовка и поместить код реализации элемента функции в файл .cpp. Это нормально и хороший способ. Тем не менее, есть другой способ. То есть напрямую написать код реализации функций участников в определение класса. В классах C ++, если элементы функций определены в теле определения класса, компилятор будет считать функцию встроенной. Следовательно, законно написать определение функций членов в орган определения класса и собрать их в файл заголовка. Обратите внимание, что незаконно писать определение функционального элемента в файле заголовка определения класса, а не в определении класса, поскольку член функции не встроен в настоящее время. После того, как файл заголовка включен в два или более файлов .cpp, этот член функции переопределен.
5. Защитные меры в файлах заголовков
Учтите, что если файл заголовка содержит только заявления об объявлении, все будет хорошо, если он будет включен в один и тот же файл .cpp много раз - потому что возникновение заявлений об объявлении неограничено. Тем не менее, три исключения в файлах заголовка, обсуждаемых выше, также являются очень распространенным использованием файлов заголовка. Затем, как только любое из трех исключений выше появляется в файле заголовка, и он включен несколько раз по A .CPP, проблема будет большой. Потому что, хотя элементы синтаксиса в этих трех исключениях «могут быть определены в нескольких исходных файлах», «могут появиться только один раз в один исходный файл». Представьте, что если AH содержит определение класса A и BH содержит определение класса B. Поскольку определение класса B зависит от класса A, AH также #Ncluded в BH. Теперь есть исходный файл, который использует как класс A, так и класс B, поэтому программист включает в себя как AH, так и BH в этот исходный файл. В настоящее время возникает проблема: определение класса A появляется дважды в этом исходном файле! Таким образом, вся программа не может быть составлена. Вы можете подумать, что это была ошибка программиста - он должен знать, что BH содержит AH, но на самом деле он не должен.
Использование «#Define» с условной компиляцией может хорошо решить эту проблему. В файле заголовка имя определяется через #define, и #ifndef ... #endif скомпилируется, чтобы компилятор мог решить, продолжать ли компилировать последующее содержание в заголовке на основе того, определено ли имя. Хотя этот метод прост, вы должны помнить, чтобы написать его при написании файла заголовка.
Спасибо, что прочитали эту статью. Я надеюсь, что подробное объяснение файлов заголовков и исходных файлов в C ++, представленное в этой статье, может помочь вам. Спасибо за вашу поддержку в новой сети технологических каналов!