Заголовки C++ - Лучшая практика, когда включая

if(dateTimeA > dateTimeB) Console.WriteLine("Do your own homework");
5
задан Jonathan Leffler 9 November 2009 в 02:21
поделиться

6 ответов

То, что вам сказал Адам Розенфилд, совершенно верно. Пример того, когда вы можете использовать форвардное объявление:

#ifndef A_H_
#define A_H_

    #include "D.h"
    class B;  //forward declaration
    class C;  //forward declaration

    class A
    {
    B *m_pb;  //you can forward declare this one bacause it's a pointer and the compilier doesn't need to know the size of object B at this point in the code.  include B.h in the cpp file.
    C &m_rc;  //you can also forware declare this one for the same reason, except it's a reference.

    D m_d;    //you cannot forward declare this one because the complier need to calc the size of object D.

    };

#endif
3
ответ дан 18 December 2019 в 05:31
поделиться

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

#ifndef _FOO_H
#define _FOO_H

...rest of the .h file...
#endif

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

Мне нравится один руководящий принцип, который выражает Адам: убедитесь, что если исходный файл просто включает ах , он не будет неизбежно возникают ошибки из-за ah при условии, что другие файлы были включены до него - например, если ah требует, чтобы bh был включен раньше, он может и должен просто включать bh сам (охранники сделают это несносным, если b. h был уже включен ранее)

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

Если вы используете классы по значению, увы, вам нужны все кровавые подробности класса в некоторых .h , которые вы включаете. Но для некоторых случаев использования с помощью ссылок или указателей будет достаточно простого class sic; . Например, при прочих равных условиях, если класс a может уйти с указателем на экземпляр класса b (то есть член class b * my_bp; , а не член ] class b * my_b; ) связь между включаемыми файлами может быть ослаблена (что значительно сокращает перекомпиляцию) - например, b.

6
ответ дан 18 December 2019 в 05:31
поделиться

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

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

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

class SomeClass;
// Can now use pointers/references to SomeClass
// without needing the full definition
22
ответ дан 18 December 2019 в 05:31
поделиться

Ответ: Пусть Ah include bh , ch и dh , только если это необходимо для успешной сборки. Основное правило: включайте в заголовочный файл столько кода, сколько необходимо. Все, что не требуется немедленно в Ah , должно быть включено в A.cpp .

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

Используя форвардные объявления везде, где это возможно, в ваших заголовочных файлах, вы уменьшаете связь исходных файлов и, следовательно сделайте сборку быстрее. Такие форвардные объявления могут использоваться во многих других ситуациях, чем вы думаете. Как правило, вам нужен только файл заголовка t. h (который определяет тип T ), если вы

  1. объявляете переменную-член типа T (обратите внимание, это не включает объявление указатель на- T ).
  2. Напишите несколько встроенных функций, которые обращаются к членам объекта типа T .

Вы делаете не , нужно включите объявление T , если ваш заголовочный файл просто

  1. объявляет конструкторы / функции, которые принимают ссылки или указатели на объект T .
  2. Объявляет функции, возвращающие Объект T по указателю, ссылке или значению.
  3. Объявляет переменные-члены, которые являются ссылками или указателями на объект T .

Рассмотрим это объявление класса; какой из включаемых файлов для A , B и C вам действительно нужно включать?:

class MyClass
{
public:
    MyClass( const A &a );

    void set( const B &b );
    void set( const B *b );
    B getB();
    C getC();

private:
    B *m_b;
    C m_c;
};

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

3
ответ дан 18 December 2019 в 05:31
поделиться

Не включать заголовки в другие заголовки - это замедляет компиляцию и приводит к циклической ссылке

0
ответ дан 18 December 2019 в 05:31
поделиться

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

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

0
ответ дан 18 December 2019 в 05:31
поделиться
Другие вопросы по тегам:

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