Допустимое использование для C ++ включает охранников, кроме того, включать в себя уступка?

StackOverflow https://stackoverflow.com/questions/4868227

Вопрос

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

#ifndef FOO_H
#define FOO_H

// ...

#endif

Немного неинтуитивно, когда его принимают (что делает FOO_H Значит?) И я склонен согласиться.

Другие говорят, что, исключая необходимость добавить больше вещей для лучшего избегания столкновений (например, PROJECTNAME_FOO_H_SDFFGH69876GF), название FOO_H это прекрасно, потому что из его контекста ясно, какова его цель (а именно, это в начале файлов с тем же именем, и ясно, что это охранник).

Я мог бы купить это, если бы единственная цель - иметь FOO_H было бы защитить от многочисленного включения, но есть ли условия, для которых я хотел бы иметь FOO_H в другом месте в файлах? Я бы подумал, что условная компиляция была бы веской причиной, в этом случае название этого что -то вроде FOO_H_INCLUDED было бы яснее.

Есть ли прямой Foward, сродни к этому, или я должен избежать перепрофилирования охранников?

Это было полезно?

Решение

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

В настоящее время принимается немного более общепринятым, определение и условное компиляцию могут использоваться для других вещей, таких как написание битов кода, которые зависят от платформы и будут компилироваться только при некоторых обстоятельствах ...

Будь то FOO_H или же FOO_H_INCLUDED лучше, я всегда буду говорить, что позже самое выразительное, и тогда я вернусь к vi и тип FOO_H в моем следующем foo.h заголовок. Опять же, как я упоминал в комментарии к другому вопросу, вы привык к образе:

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

Как первые две и последнюю строку в файле, и вы заканчиваете замечать. То есть, пока он не откусится, если вы повторно использовали одно и то же имя ...

Другие советы

Иногда я использую это для файлов заголовков «реализации». Фактическая схема именования для охранников может отличаться.

#ifndef FOO_IMPL_H
#define FOO_IMPL_H

#ifndef FOO_H
#error Don't include this directly
#endif

// Ugly implementation of the stuff in foo.h, with an uncountable
// number of template and typename keywords

#endif 

На мой взгляд, включение охранников должно включать охранников и ничего более. Если вы хотите условную компиляцию, я бы определил что -то еще. Если бы вы бросали #if defined(FOO_H) В вашем коде я думаю, что люди найдут это странным с тех пор, как _H Обычно указывает на включение охраны.

Одна вещь, о которой я могу придумать, - это проверить, был ли файл уже включен (дух!), Чтобы вам не приходилось включать файл самостоятельно. Я не уверен, будет ли это ускорить компиляцию или нет, по сравнению с заявлениями вперед или #pragma once

В main.cpp:

#include "bar.h" // comment this line to see the difference
#include "foo.h"

int main()
{
    return 0;
}

В bar.h:

#ifndef BAR_H
#define BAR_H

class BarClass
{
};

#endif

В foo.h:

#ifndef FOO_H
#define FOO_H

#if !defined(BAR_H)
#error bar h was not included // forgot how to do compiler warnings...
#include "bar.h" // we should include the file
#else
#error bar h was included // same thing, should be changed to warning
#endif

// do something with BarClass

#endif FOO_H

Я бы подумал, что условная компиляция будет хорошей причиной, в этом случае название его что -то вроде foo_h_included было бы яснее.

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

Тем не менее, это не узкое место в компиляции C ++ сегодня, и дополнительная путаница из -за того, что всегда имела форвардные объявления, либо всегда включая заголовок, не стоит.

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

Для перепрофилирования: если все содержимое файла не окружено IFNDEF/DEFINE/ENDIF, то FOO_H на самом деле не файл Включите Guard, это только охраняет часть файла. Так что, возможно, это не должно быть названо в честь всего файла. Рекурсивное включение того же файла - это одна из ситуаций, когда это может возникнуть.

Тем не менее, я подозреваю, что даже в этом случае должно быть совершенно очевидно, для чего определяется (в любом случае, более очевидно, что какая бы то ни была, что вы делаете, это не так, что не просто, включает охрану). Везде, где вы видите шаблон ifndef foo / define foo, или даже просто ifndef foo / определить много вещей, простой комментарий может сделать смысл Foo очевидным, если это уже нет.

Если какая -либо часть вопроса заключается в FOO_H может когда -либо использоваться для какой -то другой цели: я думаю, если у вас есть файл где -то uppercase.h который использует UPPERCASE_H В качестве охранника, это может быть, возможно, столкнуться с чьим -то rot13.h, содержащий #define UPPERCASE_A ('N'), и т. д. Глупый пример, но если вы определяли свойства букв в файле заголовка, то не смешно думать, что некоторые из них могут закончиться в _H.

Более реалистично, у меня были проекты с включением файлов, имеющих одинаковое базовое имя в разных каталогах.

Итак, независимо от проблемы контекста и перепрофилирования, я бы не использовал FOO_H В качестве охранника.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top