Политика заголовка C++ в отношении крупных проектов (возвращение)

Система. Данные, особенно Таблица данных,

10
задан Community 23 May 2017 в 12:13
поделиться

7 ответов

Если ваш ответ - «файл cpp должен #include каждый заголовок, который ему нужен», доведенный до логического завершения, это будет означать, что почти каждый файл cpp должен #include , и т. Д., Поскольку большая часть кода в конечном итоге будет их использовать, и если вы не должны полагаться на какой-либо другой заголовок, включающий их, ваш cpp должен включить их явно.

Ага. Я предпочитаю именно так.

Если «шум» слишком велик, можно иметь «глобальный» включаемый файл, содержащий обычный общий набор включаемых (например, stdafx.h ] во многих программах Windows) и включать его в начало каждого файла .cpp (что также помогает с предварительно скомпилированными заголовками).

8
ответ дан 3 December 2019 в 23:50
поделиться

Я думаю, вам все равно следует включить оба файла. Это помогает поддерживать код.

// Foo.cpp

#include <Library1>
#include <Library2>

Я могу прочитать это и легко увидеть, какие библиотеки он использует. Если Library2 использовал Library1 , и он был преобразован в это:

// Foo.cpp

#include <Library2>

Но я все еще видел код Library1 , я мог бы быть немного сбит с толку. Нетрудно догадаться, что какая-то другая библиотека должна включать его, но это все еще мыслительный процесс, который должен происходить.

Явность означает, что мне не нужно гадать, даже для дополнительной микросекунды компиляции.

2
ответ дан 3 December 2019 в 23:50
поделиться

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

Компромиссом может быть утверждение, что если что-то в bar.h содержит определение класса (или объявление функции), для которого обязательно требуется определение другого класса из qux.h , тогда bar.h может предполагаться / должен включать qux.h , а пользователь API в bar.h не нужно беспокоиться о включении обоих.

Итак, предположим, что клиент хочет думать о себе как о "действительно" интересующемся только API панели, но должен использовать qux тоже, потому что он вызывает функцию bar, которая принимает или возвращает объект qux по значению. Тогда можно просто забыть, что у qux есть собственный заголовок, и представить себе, что это одна большая панель API, определенная в bar.h , причем qux просто является частью этого API.

Это означает, что вы не можете рассчитывать, например, на поиск в файлах cpp упоминаний о qux.h , чтобы найти всех клиентов qux. Но я бы никогда не стал на это полагаться, поскольку в целом слишком легко случайно пропустить явно включенную зависимость, которая уже косвенно включена, и никогда не понять, что вы не перечислили все соответствующие заголовки. Так что вам, вероятно, ни в коем случае не следует предполагать, что списки заголовков завершены, а вместо этого используйте doxygen (или gcc -M, или что-то еще), чтобы получить полный список зависимостей и выполнить поиск в нем.

слишком легко случайно пропустить явно включенную зависимость, которая уже косвенно включена, и никогда не понять, что вы не перечислили все соответствующие заголовки. Так что вам, вероятно, ни в коем случае не следует предполагать, что списки заголовков завершены, а вместо этого используйте doxygen (или gcc -M, или что-то еще), чтобы получить полный список зависимостей и выполнить поиск в нем.

слишком легко случайно пропустить явно включенную зависимость, которая уже косвенно включена, и никогда не понять, что вы не перечислили все соответствующие заголовки. Так что вам, вероятно, ни в коем случае не следует предполагать, что списки заголовков завершены, а вместо этого используйте doxygen (или gcc -M, или что-то еще), чтобы получить полный список зависимостей и выполнить поиск в нем.

2
ответ дан 3 December 2019 в 23:50
поделиться

как насчет того, если foo.cpp включает bar.h и qux.h, но оказывается, что bar.h сам включает qux. час? Должен ли foo.cpp избегать включения qux.h?

Если foo.cpp напрямую использует что-либо из qux.h , то он должен включать сам этот заголовок. В противном случае, поскольку bar.h требует qux.h , я бы полагался на bar.h , включая все, что ему нужно.

1
ответ дан 3 December 2019 в 23:50
поделиться

Каждый файл заголовка содержит определения, необходимые для использования службы определенного типа (определение класса, некоторые макросы и т. Д.). Если вы напрямую используете службы, представленные через файл заголовка, включите этот файл заголовка, даже если другой файл заголовка также включает его. С другой стороны, если вы используете эти службы только косвенно, только в контексте служб другого файла заголовка, не включайте файл заголовка напрямую.

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

0
ответ дан 3 December 2019 в 23:50
поделиться

Один из способов понять, использует ли foo.cpp напрямую qux.h, - это подумать о том, что произойдет, если foo.cpp больше не будет включать bar.h. Если в foo.cpp по-прежнему необходимо включать qux.h, его следует указать явно. Если ему больше не потребуется ничего из qux.h, вероятно, нет необходимости включать его явно.

0
ответ дан 3 December 2019 в 23:50
поделиться

См. SmartDifferencer для получения информации об инструменте, который понимает синтаксис языка и абстрактные команды редактирования, такие как «перемещение этот блок кода от строки A до строки B "," переименуйте эту переменную везде в области видимости ". В настоящее время доступно для Java и COBOL, а также для других языков после Real Soon.

РЕДАКТИРОВАТЬ 04.09.2009: добавлен C # ...

РЕДАКТИРОВАТЬ 5/2011: Добавлено много языков: C ++, JavaScript, другие ... Проверить сайт .

Наш опыт показывает, что активный поиск заголовков, которые полностью не используются (или могли бы быть, с правильными предварительными декларациями), и их удаление гораздо более достойно времени и усилий, чем выяснение цепочек включения для возможные дубликаты. И хороший lint (splint, PC-Lint и т. Д.) Может помочь вам в этом определении.

Еще более достойным нашего времени и усилий было выяснить, как заставить наш компилятор обрабатывать несколько единиц компиляции на выполнение (почти линейное ускорение для нас, до определенного момента - компиляция полностью зависела от запуска компилятора).

После этого вы, возможно, захотите рассмотреть безумие "одного большого CPP". Это может быть очень впечатляюще.

с правильными форвардными объявлениями), и их удаление стоит гораздо больше времени и усилий, чем выяснение цепочек включения для возможных дубликатов. И хороший lint (splint, PC-Lint и т. Д.) Может помочь вам с этим определением.

Еще более достойным нашего времени и усилий было выяснить, как заставить наш компилятор обрабатывать несколько единиц компиляции на выполнение (почти линейное ускорение для нас, до определенного момента - компиляция полностью зависела от запуска компилятора).

После этого вы, возможно, захотите рассмотреть безумие "одного большого CPP". Это может быть очень впечатляюще.

с правильными форвардными объявлениями), и их удаление стоит гораздо больше времени и усилий, чем выяснение цепочек включения для возможных дубликатов. И хороший lint (splint, PC-Lint и т. Д.) Может помочь вам с этим определением.

Еще более достойным нашего времени и усилий было выяснить, как заставить наш компилятор обрабатывать несколько единиц компиляции на выполнение (почти линейное ускорение для нас, до определенного момента - компиляция полностью зависела от запуска компилятора).

После этого вы, возможно, захотите рассмотреть безумие "одного большого CPP". Это может быть очень впечатляюще.

Еще более достойным нашего времени и усилий было выяснить, как заставить наш компилятор обрабатывать несколько единиц компиляции за одно выполнение (почти линейное ускорение для нас, до определенного момента - компиляция полностью зависела от запуска компилятора).

После этого вы можете подумать о безумии "одного большого CPP". Это может быть очень впечатляюще.

Еще более достойным нашего времени и усилий было выяснить, как заставить наш компилятор обрабатывать несколько единиц компиляции за одно выполнение (почти линейное ускорение для нас, до определенного момента - компиляция полностью зависела от запуска компилятора).

После этого вы можете подумать о безумии "одного большого CPP". Это может быть очень впечатляюще.

0
ответ дан 3 December 2019 в 23:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: