| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > [FAQ] Множественное включение header'ов |
| Автор: archimed7592 29.12.2007, 20:23 | ||||
Хорошо бы ещё привести в коде оба этапа: 1. когда были включены и a и b. 2. когда снова был включен a(уже из b). После описания решения взять код в котором будет уже всё "включено" и построчно закомментировать мол "здесь A_H неопределён и поэтому этот кусок не будет выкинут". Потом показать окончательный код, когда уже всё выкинуто.
Какие именно (кроме MSVC). Хорошо было бы перечислить их. Не обязательно все(если их очень много, в чём я немного сомневаюсь). В общем и целом всё гут. Молодец |
| Автор: archimed7592 29.12.2007, 20:39 | ||
Угумс. Многим это непонятно. В частности, многие считают, что между именем заголовочного файла и именем модуля трансляции есть какая-то магическая связь. Укажи обязательно. Насчёт "ещё?" - не знаю, ибо конструкцией этой не пользуюсь |
| Автор: JackYF 29.12.2007, 20:48 | ||
Я тоже. Но в кодах новичков встречал.
Таки да. Хорошо, скоро сделаю. |
| Автор: JackYF 29.12.2007, 21:15 |
| Сделал. |
| Автор: archimed7592 29.12.2007, 21:21 | ||
компилятор из MS Visual Studio(MSVC), компилятор Borland C++ Builder, компилятор g++ из GCC. Добавлено через 2 минуты и 32 секунды Ну а в остальном, как я уже сказал, всё гут. Пускай повисит до "после НГ" - если критики никакой не будет, то добавим в FAQ. |
| Автор: maxim1000 29.12.2007, 22:19 |
| можно ещё в func_b() добавить параметр point *x, например чтобы яснее было, зачем в h-файле может понадобиться включение другого Добавлено @ 22:28 кстати, касательно #pragma once надёжен ли он? ведь далеко не всегда компилятор может автоматически определить, нужно ли два файла считать одинаковыми (я думаю, несложно придумать два примера, отличающиеся только семантикой и требующие разного поведения) это я к тому, что, может, стоит предостеречь о возможных трудностях, чтобы уменьшить тягу к дурным привычкам |
| Автор: JackYF 29.12.2007, 22:47 | ||
да, можно. Если никто не против, добавляю. Он нестандартен, поэтому не очень рекомендуется к использованию. Другое дело, что насчёт ненадёжности я весьма сомневаюсь - что мешает препроцессору это самое #pragma once тупо преобразовывать в #ifndef...#define...#endif? |
| Автор: maxim1000 30.12.2007, 00:50 | ||
здесь возникает вопрос идентификатора, используемого в #ifndef и #endif например, может получиться так, что в двух разных местах окажутся два файла с одинаковыми именами (ситуация не очень правильная, но возможная) и оба они должны будут использоваться в программе тогда для них нужно будет использовать разные идентификаторы (ну, можно немного модифицированные) с другой стороны может оказаться, что на самом деле, это - один и тот же файл, и включать его нужно только один раз впрочем, файлы с одинаковым содержанием - простой случай, т.к. это легко отследить, и решение использовать одинаковые идентификаторы вполне естественно однако, их содержание может быть рзаным из-за того, что это - разные версии одного и того же файла т.е. здесь возможны ситуации, когда без дополнительных знаний не разобраться |
| Автор: chipset 30.12.2007, 10:42 |
| Все MSVC поддерживают pragma once начиная c _MCS_VER 1000. ИМХО, pragma once это нормально и нечего всякое старье поддерживать А статья прикольная, +1! |
| Автор: bsa 30.12.2007, 11:34 | ||
Что стандарт говорит про #pragma once? Если он ничего говорит, то и использовать не стоит в серьезных проектах, имхо. |
| Автор: chipset 30.12.2007, 11:50 |
| А что стандарт говорит по поводу Win32API с ихними FAR поинтерами? |
| Автор: MAKCim 30.12.2007, 12:01 | ||
#pragma once гарантирует семантику #ifndef #define #endif как он это делает - детали реализации |
| Автор: bsa 30.12.2007, 12:03 | ||
WIN32API - это всего лишь библиотека со своими макроопределениями и пр. А не расширения языка. А вот #pragma once - это расширение. Есть гарантия, что оно работает на всех компиляторах поддерживающих текущий стандарт? Нет. Значит рекомендовать к использованию не стоит. |
| Автор: Mayk 30.12.2007, 12:06 | ||||||||
| Статья полезно, одно но. Длинная очень. Не знаю как ужать, но читать это сложно. Можно сэкономить пару строк выкинув func_a и изменив func_b(void) на func( struct point *pt );
имхо "явно"/"неявно" здесь лишни.
а хто это? помню что в досе ближние от дальных отличались. А вот после препроцессирования
в bcc551 получаем что нет никаких FAR поинтеров
|
| Автор: maxim1000 30.12.2007, 13:02 | ||||||||
Модераторам: может, выделить обсуждение #pragma once в свою тему? А то уже, ИМХО, оффтопик пошёл, но пообсуждать интересно
во-первых, насколько я знаю, #pragma once не является чем-то стандартизированным а это значит, что каждая реализация, которая её реализует, реализует её в своём понимании поэтому "всё остальное - детали реализации" звучит несколько странно: #pragma once целиком - деталь реализации во-вторых она попросту не может гарантировать семантику #ifndef-#define-#endif, т.к. у неё недостаточно информации чётко ответить на вопрос "являются ли файлы одинаковыми?" а если быть более точным - "нужно ли для заданной пары заголовков оставлять только один?" небольшой пример: у меня установлен VC++2005 Express, на нём я попробовал такое: создал проект в его директории создал ещё одну qqq и создал три файла: main.cpp:
aaa.h (в директории проекта)
qqq/aaa.h
при компиляции получил ошибку двойного определения "x" судя по этому, VC++ сравнивает файлы по их полному имени (с путём) значит, эти два файла для неё - разные однако, вполне возможна такая ситуация, окгда программист будет таскать с собой, к примеру, какой-нибудь файлик с нужными вещами, который он использует везде, а когда начнёт объединять какие-то два проекта, полезут ошибки зато если бы использовались #ifndef AAA_H_ #define AAA_H_ ... #endif, никаких ошибок не было бы -------------------------------- конечно, можно возразить: "ну не знаю, что там VC++, вот мой компилятор в даном случае будет считать их одним файлом" это чудесно, но та же ситуация могла бы случиться, когда эти файлы семантически разные, например, какой-нибудь config.h в разных поддиректориях может конфигурировать разные части программы в данном случае уже ошибётся компилятор, который будет считать, что они одинаковые потому я и говорю - на данный момент нет достаточного инструментария, чтобы создать полностью автоматическую #pragma once... впрочем, насколько я слышал, в следующем стандарте предполагаются движения в эту стороны, и я более чем уверен, что простым добавлением ключевого слова дело не ограничится... |
| Автор: JackYF 30.12.2007, 14:08 |
Понимаю. Но я тоже не знаю, как особо ужать. Раскрыть тему желательно полнее, чтобы не оставалось вопросов по теме. Хм... ну не знаю. Мне так не кажется. Камрады, что скажете? Оставлять/убирать? |
| Автор: archimed7592 30.12.2007, 17:38 | ||||
Здесь обсуждайте - полезнее для статьи. Убирать не нужно. Возможно, что стоит перефразировать, если сможете придумать как(у меня идей нет)
Если файлик общий, то его нужно выделить в одно место(общее для обоих проектов), что даст явные преимущества и, в том числе, не будет ошибки с сабжевой прагмой. OTOH, что бы ни говорили, я против использования прагм, когда есть стандартные заменители. |
| Автор: maxim1000 30.12.2007, 21:11 | ||
так я сразу написал, что при более-менее логичной структуре файлов проекта и их имён больших проблем быть не должно но ведь далеко не всегда структура логична особенно объединение двух проектов: далеко не всегда код обоих проектов может контролирвоаться (third party всякие), а эта конструкция добавит кучу ошибок, причин для которых в общем-то нету... P.S. всё это было к тому, что, может, стоит добавить какое-то предупреждение о возможных проблемах |
| Автор: archimed7592 30.12.2007, 21:19 | ||
Возможно, что лучше вообще не упоминать о прагме, либо написать отдельную статью о вреде прагмы и давать в ФАКе ссылочку на описание вреда прагм |
| Автор: JackYF 3.1.2008, 14:20 |
так... сделано. Ещё замечания будут, или будем выкладывать? |
| Автор: archimed7592 3.1.2008, 14:22 |
Думаю, что не будет, но кто их знает Обожди выкладывать - сейчас у многих выходные. |
| Автор: JackYF 3.1.2008, 14:38 |
Хорошо, "обождеваю" |
| Автор: MAKCim 3.1.2008, 14:57 | ||
если препроцессор поддерживает #pragma once то значит он каким-то образом реализует семантику #ifndef #define #endif а уж как - детали реализации в конкретном препроцессоре нам об этом беспокоится не стоит поведение будет ожидаемым как можно реализовать? легко #pragma once -> #ifndef NAME #define NAME #endif где NAME - трансформируемый абсолютный путь к текущему заголовочному файлу т. е для Linux, к примеру, если абсолютный путь к файлу - /home/user/include/math.h то трансформируемый абсолютный путь - homeuserincludemathh для Windows, если абсолютный путь - d:\user\include\math.h то трансформируемый абсолютный путь - duserincludemathh т. к в одной и той же директории не может быть двух файлов с одинаковым названием, то абсолютный путь уникально трансформируется в NAME |
| Автор: archimed7592 3.1.2008, 15:01 |
В данном случае не совсем уникально, ну да ладно |
| Автор: MAKCim 3.1.2008, 15:08 |
| maxim1000, + твой пример не работает не из-за #pragma once замени #pragma once на #ifndef #define #endif у тебя все равно не будет работать если конечно в #define обоих файлов будет не одинаковый идентификатор + то, что ты показал примером - имхо, неправильно потому что ты из двух физически разных файлов хочешь сделать семантически эквивалентные Добавлено через 1 минуту и 44 секунды в смысле? приведи пример 2-ух разных файлов, для которых NAME будут одинаковые при использовании моего алгоритма |
| Автор: archimed7592 3.1.2008, 15:19 | ||
/home/user/math.h и /home/usermath.h |
| Автор: bsa 3.1.2008, 15:20 | ||
| /home/user/include/math.h и /home/user/include/m/ath.h Добавлено через 18 секунд не успел Добавлено через 11 минут и 24 секунды как вариант, можно заменять спецсимволы на коды: _<HexCode>:
|
| Автор: MAKCim 3.1.2008, 17:19 |
| archimed7592, ага согласен но смысл от этого не меняется ввести дополнительные правила тогда будет точно все однозначно |
| Автор: archimed7592 3.1.2008, 17:21 |
Да я сразу сказал: |
| Автор: MTWizard 8.1.2008, 17:03 |
| Кстати, с каких это времён Builder поддерживает #pragma once? Я писал на 6-м, 2006, 2007 - там эти прагмы просто игнорируются. |
| Автор: JackYF 8.1.2008, 17:06 | ||
да-а? странно, а чего тогда кодогенератор Билдера их в исходники вставляет? просто так? |
| Автор: bsa 8.1.2008, 17:32 |
| JackYF #pragma once не видел ни разу. а вот #pragma argsused и #pragma hdrstop встречаются. |
| Автор: MTWizard 8.1.2008, 18:36 | ||||||
| Вот именно. Только что перепроверил. C++ Builder 2007 Update 2. Файлы: File.cpp:
File.h:
Вылезает ошибка:
Стоит добавить header guard, как ошибка устраняется. Вывод: Builder не поддерживает #pragma once |
| Автор: JackYF 8.1.2008, 20:44 |
оппа. Приехали... Значит, надо убирать из списка, скоро поправлю. MTWizard, спасибо за информацию. |
| Автор: SergeCpp 9.1.2008, 09:54 |
| Некоторая информация относительно #include, include guards, #pragma once, скорости компилирования etc. http://gamearchitect.net/Articles/ExperimentsWithIncludes.html http://www.gamesfromwithin.com/articles/0501/000067.html http://www.convexhull.com/mt/mt-comments.cgi?entry_id=67 |
| Автор: JackYF 9.1.2008, 10:12 |
| SergeCpp, почитал, спасибо. Правда, к самому FAQ'у это имеет мало отношения. |
| Автор: archimed7592 10.1.2008, 11:27 |
| Так замечаний больше вроде нет. Главред Евгений, статья на Ваш взгляд готова? Можно приступать к окончательной вычитке мною? |
| Автор: JackYF 10.1.2008, 12:08 |
Итак, это поправил, Билдер из списка убрал. |
| Автор: warmonger_ 10.1.2008, 13:53 | ||||
а какой конструкцией нужно пользоваться? есть альтернатива? ( кроме сказаного #pragma once) |
| Автор: JackYF 10.1.2008, 14:44 |
ты статью вообще читал? она почти готова, прочитай, пожалуйста. Первый пост в теме. |
| Автор: archimed7592 10.1.2008, 16:50 | ||
|
| Автор: warmonger_ 10.1.2008, 20:26 | ||
Первый пост читал. Я имел ввиду кроме #pragma once, #ifndef...#define...#endif. Извините, я неверное не так понял. |
| Автор: archimed7592 10.1.2008, 20:35 | ||
Наверняка.
|
| Автор: bsa 10.1.2008, 21:02 |
| Ну вот. Все-таки в другое измерение засунули... archimed7592, сделай хотя бы ссылку в прикрепленной теме на форуме на весь FAQ. А то новички туда вряд ли пойдут. |
| Автор: JackYF 10.1.2008, 21:06 |
что в этом способе тебя не устраивает? Добавлено через 8 минут и 44 секунды archimed7592, я увидел вот это в середине поста. Что ты хотел сделать? [code=nocolor]a.h:1: error: redefinition of ‘struct point’[/QUOTE] Добавлено через 13 минут и 26 секунд уже поправил последнее. |
| Автор: archimed7592 10.1.2008, 21:30 | ||
Будет, будет. Как только хотя бы текущие статьи(те что в разработке) завершат, так сразу и будет(я уже об этом думал). Ooopps |
| Автор: warmonger_ 10.1.2008, 21:35 |
я же уже написал, что не правильно понял |