Джон дает хороший совет, но вот немного больше фона на whys, wherefores и exceptions.
Для предотвращения импорта заголовков в заголовки есть две цели: улучшенные инкрементные времена сборки и избежание круговых зависимостей. Если импортировать A.h
в B.h
и импортировать B.h
в C.h
, то каждый раз, когда вы что-либо изменить в A.h
, вы должны перекомпилировать C.m
, даже если C.m
не использует какой-либо из вещей, определенных в A.h
. Это может привести к действительно ужасному и ненужному сбою в сборе, особенно если у вас есть заголовки, которые часто меняются (как это принято на ранних этапах разработки).
Первый гол похвален, но для небольших проектов, кого это волнует? У вас есть четырехъядерный Pro, а полная сборка занимает пару минут, верно? Но вам все равно придется беспокоиться о второй проблеме: круговые зависимости. A.h
ссылки класс B
и B.h
ссылки класс A
. Это на самом деле может произойти довольно часто и может проникнуть в систему совершенно невинно. Объект коллекции может ссылаться на тип объектов, которые он содержит, и объекты могут ссылаться на тип объекта коллекции. Все, что требуется, это единственная ссылка из-за некоторого метода, который принимает или возвращает этот тип. Если у вас есть заголовки, импортирующие другие заголовки, вероятность этого быстро приближается к единству. Вы завершаете рекурсивный импорт, и ошибки времени компиляции могут быть размытыми. «Я знаю, что определяется typdef!Это прямо сейчас! Он импортирован! »Но он еще не разобрался, когда вы импортировали в этот заголовок. Это то, что вызывает вашу ошибку выше.
По этой причине, даже если вам все равно не так много времени на сборку (хотя вы должны), избегать импорта заголовков в заголовки ... кроме ....
некоторых заголовков вы имеете импортировать. Ваш суперкласс конечно. файлы, которые определяют @protocol
, обеспечиваемые или typedef
вы используете. Так что да, вы должны включить их.
А как насчет системных заголовков? Ну, они никогда не спят ause churn, и, очевидно, они не будут вызывать рекурсивный импорт, поэтому они в порядке. Я препятствую людям использовать @class
передовые декларации для вещей в заголовках системы. Это создает дополнительную работу с пользователем вашего заголовка без какой-либо ценности. Для хорошей гигиены заголовка, пожалуйста, не забудьте закрепить заголовки системы в квадратных скобках < > и ваши заголовки в «кавычках».
Итак, это не тривиальный вопрос, но простое правило: избегать импорта заголовков пользователей в другие заголовки пользователей в любое время, когда компилятор позволит вам.
Как насчет 'typedef' и 'протоколов'? – Joost
Вы бы не узнали о учебнике или образце кода, который использует это? – gargantuan