Проблема множественного включения заголовочных файлов(headers)
Пример:
Пускай программа состоит из трёх файлов — main.cpp, a.h, b.h.
a.h:
Код |
|
b.h:
Код |
|
main.cpp:
Код |
|
В заголовочном файле a.h описывается структура point и объявляется функция func_a.
В заголовочном файле b.h включается заголовочный файл a.h и объявляется функция func_b.
В основном файле программы main.cpp подключаются заголовочные файлы a.h и b.h, в функции main() поочерёдно вызываются функции func_a, func_b, затем программа завершается.
Проблема:
Программа не компилируется. Компилятор выдаст ошибку, например так:
Код |
a.h:1: error: redefinition of ‘struct point’ |
Почему так происходит?
Директива компилятора #include говорит компилятору о том, что содержимое указанного файла нужно вставить в данное место.
Описание структуры point, итого, вставится в main.cpp два раза: 1-й раз — явно — при включении файла a.h, второй раз — неявно — при включении файла b.h, так как файл b.h тоже включает в себя содержимое файла a.h.
Код главного модуля сначала преобразуется в такое:
Код |
|
После чего снова обрабатывается #include и получается:
Код |
|
В этом, итоговом, коде присутствуют два определения struct point. Это и служит причиной выдачи ошибки компилятором.
Решение:
Использовать условные директивы компилятора #ifndef…#define…#endif.
Их также называют «стражами включения».
Код всех заголовочных файлов нужно обрамлять:
Код |
|
Идентификатором файла может быть любое правильной имя переменной в С/С++.
Однако, принято давать этим иденфикаторам имена, состоящие из больших букв латинского алфавита и подчёркиваний, логические связанные с именем файла.
К примеру, для файла abcd.h можно взять идентификаторы ABCD_H, FILE_ABCD_H, ABCD_H_INCLUDED
Важно: идентификаторы заголовочных файлов в пределах одной программы(одного проекта) должны быть разными, иначе Вы получите обратный результат(не множественное включения, а отсутствие включения).
Исправленный заголовочный файл a.h:
Код |
|
Работа этих директив в данном случае заключается в том, что в первой строчке проверяется, не определено ли A_H_INCLUDED. Если определно, значит, содержимое данного файла уже было включено, и компилятору не надо обрабатывать содержимое файла повторно. Если же нет, то определяем A_H_INCLUDED и обрабатываем дальше заголовочный файл.
В этом случае, код модуля с учётом произведённых #include имеет вид:
Код |
|
Итого получается следующее:
Код |
|
Это и есть желаемый нами код.
Данное решение работает на всех известных компиляторах С/С++.
Замечания:
1. В данном примере файл b.h тоже желательно должен быть обрамлён.
2. Не начинайте имя идентификатора с подчёркивания, это крайне не рекомендуется стандартом С++.
Другие решения.
Некоторые компиляторы С/С++ предоставляют ещё одно решение проблемы.
Для этого необходимо включить в начало каждого заголовочного файла директиву
Данная директива имеет тот же эффект, что и вышеприведенное решение, но для её применения потребуется компилятор, поддерживающий это расширение. В число таких компиляторов входят: компилятор из MS Visual Studio (MSVC), компилятор g++ из GCC.
Назад к FAQ
Это сообщение отредактировал(а) bsa — 26.7.2011, 11:02
Я новичок в C ++, и я пытаюсь выучить его для вступительных испытаний в моей школе, чтобы пройти курс информатики, который я хочу.
Мне пришлось написать программу, которая создала бы массив и использовала значения, которые они мне дали для строк и столбцов.
Программа использует функцию, чтобы найти сумму наибольшего ряда целых чисел.
#include <iostream>
using namespace std;
int findMaxSumArray (int arr[3][3])
{
int sum1, sum2 = 0;
int i, j = 1;
int row = 3;
int col = 3;
for (i = 0; i < row; ++i)
{
sum1 = sum1 + arr[1][i];
}
for (j = 2; j < col; ++j)
{
for (i = 0; i < row; ++i)
{
sum2 = sum2 + arr[j][i];
}
if (sum2 > sum1)
{
sum1 = sum2;
}
}
return sum1;
}
int main ()
{
int arr[3][3] = { {1, 2, 3}, {2, 3, 4}, {5, 6, 7} };
cout << findMaxSumArray(arr);
}
К этому моменту я получил свой код для возврата правильного ответа на другие онлайн-компиляторы, но тот, который используется для теста, продолжает выдавать мне эту ошибку. Я рассмотрел причины ошибки, и все они кажутся несвязанными, включая два файла, ссылающихся на main вместе.
Вот ошибки, которые я получаю:
Syntax Error(s)
prog.cpp: In function 'int main()':
prog.cpp:46:5: error: redefinition of 'int main()'
int main() {
^
prog.cpp:38:5: note: 'int main()' previously defined here
int main ()
^
Я немного растерялся из-за того, почему я мог получить эту ошибку на некоторых, но не на всех компиляторах. Я не полностью понимаю C ++, поскольку я изучаю это. Может ли кто-нибудь из вас пролить свет на эту проблему?
0
Решение
Это не связано с вашим вопросом, но есть еще одна проблема в вашем коде — вы используете неинициализированную локальную переменную.
Несмотря на то, что это может выглядеть, эта строка кода не инициализируется sum1, он только объявит это:
int sum1, sum2 = 0;
Чтобы сделать это более понятным, мы могли бы переписать его следующим образом: значение будет таким же:
int sum1;
int sum2 = 0;
Локальные переменные не получают нулевой инициализированный по умолчанию (как глобальные переменные), это означает, что они будут иметь некоторое значение, но мы не можем предсказать его.
Как вы можете догадаться, используя var1 не даст ожидаемых результатов.
sum1 = sum1 + arr[1][i]; //!!
Вместо этого это вызовет странные ошибки.
1
Другие решения
Других решений пока нет …
Алехандрыч 0 / 0 / 0 Регистрация: 07.11.2016 Сообщений: 4 |
||||
1 |
||||
07.11.2016, 22:16. Показов 9535. Ответов 2 Метки c++ (Все метки)
Что тут не так?
__________________
0 |
Cheshyrsky_Kot 0 / 0 / 1 Регистрация: 28.05.2015 Сообщений: 30 |
||||
07.11.2016, 23:49 |
2 |
|||
Алехандрыч, Ты в начале задал тип данных для «i» Добавлено через 4 минуты
0 |
0 / 0 / 0 Регистрация: 07.11.2016 Сообщений: 4 |
|
08.11.2016, 15:28 [ТС] |
3 |
Спасибо большое помог!
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
08.11.2016, 15:28 |
Помогаю со студенческими работами здесь Какая из этих функций int Q(int w) int W(int y,int u,int i) сработает быстрее? ОШИБКА [Error] cannot convert ‘int*’ to ‘float*’ for argument ‘1’ to ‘void Syma(float*,int*,int) Ошибка: error: invalid types ‘int[int]’ for array subscript Ошибка — перегруженность pow(int,int) неосуществима. Как исправить? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 3 |