Q: Зачем нужны заголовочные файлы?

A: В С++ есть такое правило - «правило одного определения» (One Definition Rule). Оно (среди прочего) требует: 1. В одной единице трансляции (для простоты - одном cpp-файле) должно быть только одно определение определенного класса/функции/перечисления. Т. е. следующий исходный текст будет считаться некорректным:

// main.cpp
 
struct A
{
int x;
int y;
};
 
struct A
{
int x;
int y;
int z;
};

Потому что в нем два определения класса A, что нарушает правило одного определения.

2. Если в разных единицах трансляции (cpp-файлах) определны одноименные классы/функции/перечисления, и они представляют одну и туже сущность, то их определения должны быть идентичны (определение этой идентичности можно найти в стандарте). Т. е. следующий пример будет некорректным:

// file1.cpp
 
struct A
{
int x;
int y;
};
 
void foo1(const A& a)
{
std::cout << a.x << " " << a.y << std::endl;
}
 
// file2.cpp
struct A
{
int z;
int y;
int x;
};
 
void main()
{
A a = {1, 2, 3};
foo1(a);
}

Потому что в файлах file1.cpp и file2.cpp определения класса A не совпадают. Так вот, для того, чтобы не перечислять всякий раз во всех файлах проекта одни и теже функции/классы (с возможностью допустить при этом ошибку), все эти определения выносят в заголовочные файлы, после чего эти файлы включают в каждую единицу трансляции, где требуются необходимые определения. При этом в заголовочные файлы вносят т. н. охранные макроопределения:

// file.h
#ifndef file_h__
#define file_h__
 
// здесь идет перечисление необходимых определений
 
#endif

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

// common.h
 
class A {};
 
// file1.h
#include "common.h"
class B : public A
{
}
 
//file2.h
#include "common.h"
class C : public A
{
};
 
// main.cpp
#include "file1.h"
#include "file2.h"

Компиляция main.cpp завершится ошибкой, т. к. в нем будут присутствовать два определения класса А (включенные через file1.h и file2.h). В случае использования охранных макросов:

// common.h
#ifndef common_h__
#define common_h__
 
class A {};
 
#endif

при обработке файла file2.h компилятор (точнее, препроцессор) увидит, что макроопределение common_h__ уже определено, условие выполнено не будет, и текст файла не будет включен (повторно) в main.cpp.

 
faq/c_c_/language/header_files_purpose.txt · Последние изменения: 2006/05/10 14:19 (внешнее изменение)
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki