Не сказать, что Google Style Guide — это священная библия, но как программист-новичок он кажется хорошим справочником.
Руководство по стилю Google перечисляет следующие недостатки предварительного объявления
Прямые объявления могут скрывать зависимость, позволяя пользовательскому коду пропускать необходимую перекомпиляцию при изменении заголовков.
Предварительная декларация может быть нарушена последующими изменениями в библиотеке. Прямое объявление функций и шаблонов может препятствовать тому, чтобы владельцы заголовков могли вносить в свои API-совместимые изменения, в противном случае такие, как расширение типа параметра, добавление параметра шаблона со значением по умолчанию или миграцию в новое пространство имен.
Вперед объявление символов из пространства имен std :: приводит к неопределенному поведению.
Может быть трудно определить, требуется ли предварительное объявление или полный #include. Замена #include на предварительную декларацию может незаметно изменить значение кода:
Код:
// b.h:
struct B {};
struct D : B {};
// good_user.cc:
#include "b.h"void f(B*);
void f(void*);
void test(D* x) { f(x); } // calls f(B*)
Если #include заменить на forward decls для B и D, test () вызовет f (void *).
Прямое объявление нескольких символов из заголовка может быть более подробным, чем простое включение заголовка.
Структурирование кода для включения прямых объявлений (например, использование элементов указателя вместо элементов объекта) может сделать код медленнее и сложнее.
Тем не менее, некоторые поиски в SO, похоже, наводят на мысль, что предварительное объявление является универсальным лучшим решением.
Итак, учитывая эти, казалось бы, нетривиальные недостатки, может ли кто-нибудь объяснить это несоответствие?
И когда безопасно игнорировать некоторые или все эти недостатки?
некоторые поиски на SO, казалось, предположили, что предварительное объявление
универсально лучшее решение.
Я не думаю, что так говорит ТАК. Текст, который вы цитируете, сравнивает «партизанскую» форвардную декларацию с включением надлежащего включаемого файла. Я не думаю, что вы найдете большую поддержку SO для подхода, который Google критикует здесь. Это плохой подход: «Нет, не #include
включите файлы, просто напишите объявления для нескольких функций и типов, которые вы хотите использовать «.
Надлежащий файл включения будет по-прежнему содержать собственные предварительные объявления, и поиск в SO покажет, что это правильно, поэтому я понимаю, откуда у вас идея, что SO поддерживает декларации. Но Google не говорит, что собственный подключаемый файл библиотеки не должен содержать предварительных объявлений, он говорит, что вы не должны заниматься мошенничеством и писать собственные предварительные объявления для каждой функции или типа, которые вы хотите использовать.
если ты #include
правильный включаемый файл, и ваша цепочка сборки работает, тогда зависимость не скрыта и остальные проблемы в основном не применяются, несмотря на то, что включаемый файл содержит объявления. Есть все еще некоторые трудности, но это не то, о чем Google говорит здесь.
Рассматривая, в частности, предварительные объявления типов по сравнению с определениями классов для них, (4) дает пример того, что происходит неправильно (поскольку предварительное объявление D
не может выразить, что это происходит от B
, для этого вам нужно определение класса). Есть также техника под названием «Pimpl», которая делает осторожный использование прямого объявления типа для конкретной цели. Итак, снова вы увидите некоторую поддержку SO для этого, но это не то же самое, что поддержка идеи каждый должен вообще бегать объявляющие вперед классы вместо #include
их заголовочные файлы.
От Тита Винтерса CppCon 2014 talk:
Самое важное, что мы узнали в последнее время: «Вперед, объявляя что-либо с шаблоном, это действительно плохая идея. Это привело к проблемам с обслуживанием, как вы не поверите. Форвардная декларация может быть в порядке, в немного случаи? Я подозреваю, что правило действительно изменится на: Владельцам библиотек предлагается предоставить заголовок, который специально направляет декларацию того, что, по его мнению, стоит того (выделение добавлено), и вам, вероятно, не следует пересылать объявление самостоятельно, и никто не должен пересылать объявление шаблонного типа. Посмотрим. Мы все еще прорабатываем [неразборчиво] детали из того, что мы узнали.
Так что, возможно, проблемы с попыткой прямого перенаправления объявленных шаблонных типов могут быть одним из их мотивов препятствовать оптовой форвардной декларации …?
Кроме того, предоставление «заголовка, который специально пересылает, объявляет вещи, которые, по их мнению, стоят того», звучит аналогично тому, как <iosfwd>
используется, как описано Вот (Решение 2.2), Вот, а также Вот.
РЕДАКТИРОВАТЬ:
Чтобы было ясно, я не говорил, что я согласен или не согласен с тем, что Google не одобряет предварительную декларацию. Я просто пытался понять их обоснование и сделал в сторону / наблюдение <iosfwd>
,
Лично я использую предварительные декларации, когда могу, следуя указаниям, изложенным далее в том же GOTW ссылка выше (решение 3):
Руководство: Никогда
#include
заголовок, когда будет достаточно предварительного объявления.
но рассуждения Уинтерса, похоже, тоже имеют свои достоинства. Я работал над кодом, в котором я пересылаю объявленные шаблонные типы из сторонней библиотеки, и синтаксис становится беспорядочным (я еще не сталкивался с проблемами обслуживания, на которые ссылался Винтерс). ОТО, я не уверен в том, чтобы обескуражить все предварительные объявления, как указано в Руководстве по стилю Google C ++, но я думаю, что это работает для Google?
Отказ от ответственности: я не эксперт, все еще учусь.