Подтвердить что ты не робот

Рекомендации по использованию файлов заголовков С++

У меня есть следующие сомнения в использовании файлов заголовков.

1 - Включить защиту после комментариев

/* Copyright Note and licence information (multiple lines) */
#ifndef FOO_H
#define FOO_H
// Header file contents
#endif

Трава Саттер говорит в своей книге "Стандарты кодирования на C++", что такой код, как выше, проблематичен. Он говорит, что операторы "#ifndef" должны появиться в первой строке файла заголовка. Я не считаю это убедительным. За этим следуют вы, парни/галы, в заголовочных файлах?

2 - Использование пространств имен в файлах заголовков

#ifndef FOO_H
#define FOO_H
namespace FooNameSpace{
    // Header file contents
}
#endif

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

Если приведенный выше метод является правильным, как вы выполняете "форвардную декларацию" класса, который находится в другом пространстве имен? Это как

#ifndef FOO_H
#define FOO_H
namespace AnotherNameSpace{
    class AnotherFoo; // forward declaration
}

namespace FooNameSpace{
    // Use AnotherFoo here
}
#endif

"Прямое объявление" - единственный способ избежать "циклической зависимости", правильно?

4b9b3361

Ответ 1

  • Порядок включенных охранников и комментариев - это просто вопрос стиля - он не будет иметь измеримого влияния на скорость компиляции.

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

Примеры:

// WRONG!
using namespace std;
class MyClass
{
    string stringVar;
};

// RIGHT
class MyClass
{
    std::string stringVar;
};

Что касается передовых объявлений классов в других пространствах имен, у вас есть это точно. Не забудьте всегда квалифицировать AnotherFoo как AnotherNameSpace::AnotherFoo, когда вы ссылаетесь на него внутри своего заголовка. Действительно, передовые декларации - единственный способ разбить циклические зависимости.

Ответ 2

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

  • Конечно, заголовки должны включать пространства имен - иначе ничего полезно когда-либо быть внутри Пространство имен. Однако, поскольку вы упомянутые заголовки не должны "импорт" (из-за отсутствия лучшего слова) пространства имен в блок компиляции с директивой 'using.

Ответ 3

Что касается № 1, я не знаю никаких конкретных аргументов за или против. У многих компаний есть политика, в которой уведомление об авторских правах должно быть первым пунктом в файле ДО того, что-либо еще или какой-либо значимый код (возможно, предполагается, что вы прочитаете авторское право до того, как будете поглощать какой-либо код). Для этой цели #IFNDEF уже является кодом. С точки зрения удобства использования, имеет смысл сначала поставить авторские права, потому что глаз игнорирует их. Однако все, что описывает модуль, должно появиться после #ifndef, на мой взгляд.

Ответ 4

1) Поскольку комментарии на самом деле ничего не делают, я сомневаюсь, что это имеет большое значение. Технически, #include copy и pastes, поэтому помещать комментарии вне защитников заголовков может означать больше работы для препроцессора. Я не знаю, достаточно ли для большинства компиляторов достаточно оптимизировать для этого (т.е. Если они отделяют комментарии до этапа препроцессора), но вы, вероятно, не заметили бы, пока не достигнете десятков тысяч файлов заголовков.

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

Ответ 5

  • Я не думаю, что добавление комментариев имеет какое-либо влияние на производительность, как указал Адам на этот пост.

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

Использование ключевого слова "using" точно не ошибочно (поскольку оно дает вам много удобства и намного меньше, чем печатать перед всеми вашими переменными)