Есть ли веская причина использовать защитные ограждения в файлах h вместо файлов cpp? - PullRequest
0 голосов
/ 25 февраля 2020

Например, из моего базового c понимания C ++ и clang ++ я не понимаю, почему следующая установка не будет предпочтительной:

Кажется, что использование варианта с заголовками даст больше для вывода требуется более конкретная c настройка компилятора и двойственность в объявлении функций.

clang++ --std=c++2a Start.cpp -o Start.o; ./Start.o

Start. cpp

#include "A.cpp"
#include "B.cpp"

int main (
    int argc,
    char** argv
) {
    A();
    B();

    return 0;
}

A. cpp

#ifndef A_H
#define A_H

#include <stdio.h>
#include "C.cpp"

void A() {
    printf("A\n");
    C();
}

#endif

B. cpp

#ifndef B_H
#define B_H

#include <stdio.h>
#include "C.cpp"

void B() {
    printf("B\n");
    C();
}

#endif

C. cpp

#ifndef C_H
#define C_H

#include <stdio.h>

void C() {
    printf("C\n");
}

#endif

1 Ответ

2 голосов
/ 25 февраля 2020

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

Кроме того, оно Обычно компилируются cpp файлы и связываются между собой. Если вы оба скомпилируете какой-либо из этих cpp файлов, а также включите его в другой модуль перевода, вы столкнетесь с этим сценарием нарушения ODR.

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

Кроме того, рекомендуется придерживаться часто используемой схемы именования. , Использование расширения cpp для заголовочных файлов противоречит всем распространенным схемам именования.

Есть ли веская причина использовать защиту в файлах h вместо файлов cpp?

Вы всегда должны использовать include guard во всех заголовочных файлах, независимо от того, как вы называете заголовочные файлы. (хотя технически средства защиты заголовков не нужны в некоторых заголовках, но проще просто использовать защиту заголовков, чем отслеживать, нужно ли вам это или нет).


Теперь, если вам интересно можете ли вы поместить все свои определения функций в одну единицу перевода: да, вы можете. Это имеет свои преимущества и недостатки:

Преимущество одного TU: более быстрое время компиляции с нуля из-за отсутствия повторения компиляции шаблонов и других встроенных функций. Также лучшая оптимизация, потому что нет границ блока перевода, которые могли бы помешать оптимизации - это преимущество уменьшается за счет оптимизации времени соединения, которая работает через границы TU.

Недостаток: любое изменение в программе вызывает перекомпиляцию только измененных единиц перевода. Когда есть только одна единица перевода, которая является всей программой, то любое изменение, независимо от того, насколько оно мало, потребует перекомпиляции всей программы. Это крайне нежелательно. Этот недостаток уменьшается за счет оптимизации времени соединения, которая может привести к тому, что соединение будет настолько медленным, что время, сэкономленное на повторно используемых единицах перевода, может стать незначительным.

...