Действительно ли требование является определенным порядком на #includes в C++ знак плохого дизайна библиотеки/заголовка?

Вы можете сделать только:

your_list = [your_list] * 30
12
задан ApplePieIsGood 17 December 2008 в 19:02
поделиться

13 ответов

Библиотека STL или STD или даже Повышение имеют какие-либо случаи, где бесспорный включает, должен существовать определенного порядка?

Для стандарта ответ решительно, нет. Я предполагаю, что то же верно для Повышения, хотя я не искал его.

Из стандарта C:

Стандартные заголовки могут быть включены в любой порядок; каждый может быть включен несколько раз в данном объеме, без эффекта, отличающегося от того, чтобы быть включенным только однажды, за исключением того, что эффект включения <assert.h> зависит от определения NDEBUG (см. 7.2).

стандарт C++ имеет подобную формулировку.

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

28
ответ дан 2 December 2019 в 02:58
поделиться

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

До повышения и STL, я вполне уверен, я еще не встретился с этой ситуацией.

9
ответ дан 2 December 2019 в 02:58
поделиться

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

// A.cpp
#include "A.h"
#include "boost/shared_ptr.hpp"
#include <vector>

class A {
// ...
};

Если этот путь, если, например, A.h будет использовать вектор без права #include, то A.cpp не скомпилирует.

Я не могу помнить, где я взял это; это, возможно, был от "Крупного масштаба Дизайн C++" Lakos (замечательная книга, которая могла действительно использовать обновление).

9
ответ дан 2 December 2019 в 02:58
поделиться

Библиотека STL или STD или даже Повышение имеют какие-либо случаи, где бесспорный включает, должен существовать определенного порядка?

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

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

Это - общая техника для включения заголовка совместимости уровня проекта (скажите, что compat.h) как первый заголовок любых .c/.cpp исходных файлов, который определяет набор необходимых макросов как __ STDC_LIMIT_MACROS, __ ПОВТОРНО ИСПОЛЬЗУЕМЫЕ и другие широкие макросы проекта для влияния на последующее поведение стандартных заголовков.

Я увидел это использование в первый раз давным-давно компетентным программистом для внутренней библиотеки. Позже я видел 'мерзавца' (печально известный dvcs), проект использует эту технику также.

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

Это - 'плохая вещь'. Был упомянут лучший путь; но я уточню.

//a.h
#ifndef _A_H_
#define _A_H_

//... code ...

#endif
// -----------------
//b.h
#ifndef _B_H_
#define _B_H_
#include a.h

//... code ...

#endif
// -----------------
//main.cpp Try 1
#include "b.h" //<- okay!  b includes a, then does b
// -----------------
//main.cpp Try 2
#include "a.h" //<- includes a
#include "b.h" //<- okay!  b includes a, but skips redefining it, then does b
// -----------------
//main.cpp Try 3
#include "b.h" //<- b includes a, then does b
#include "a.h" //<- okay!  a skips redefining itself!
// -----------------
//main.cpp Try 4
#include "a.h" //<- fail!  b is not included anywhere =(
3
ответ дан 2 December 2019 в 02:58
поделиться

Если функции и/или классы, содержавшиеся в заголовке (говорят, A.h), зависят от функций, и/или классы, определенные в другом заголовке (скажите, B.h), я предпочитаю быть последнего в первое, скорее вынуждать пользователей первого включать обоих в особый порядок.

Да:

// A.h
#pragma once
// or the #ifndef trick
#include "B.h"

// A.cpp
#include "A.h"

Нет:

// A.h
#pragma once
// or the #ifndef trick
//#include "B.h"

// A.cpp
#include "B.h"
#include "A.h"
2
ответ дан 2 December 2019 в 02:58
поделиться

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

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

1
ответ дан 2 December 2019 в 02:58
поделиться

Мне это - плохой дизайн, который, к несчастью, оказывается, находится в win32 API с socket/socket2, включает, если я вспоминаю правильно. Результат состоит в том, что ошибка в порядке включения инициирует ряд ошибок, которые просто, оказывается, прибывают из ниоткуда и могут быть трудны отладить в случаях, где зависимость изменяет определения, но код все еще компилирует.

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

1
ответ дан 2 December 2019 в 02:58
поделиться

Это - возможно, знак, что Вы используете MFC, который мог бы в свою очередь указать на плохой дизайн (шутка..., или это?)

(По крайней мере, в прошлый раз, когда я посмотрел на MFC, это было действительно требовательно в отношении того, где Вы включали <windows.h>)

1
ответ дан 2 December 2019 в 02:58
поделиться

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

Иногда все еще требуется, что заголовок включен сначала или в последний раз, никакая идея почему.
(Например: В Источнике SDK)

0
ответ дан 2 December 2019 в 02:58
поделиться

Да, требование определенного порядка на включает в C++, знак плохого дизайна библиотеки/заголовка.

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

//A.h

class B; // forward declaration

class A
{
    void doStuff(const B& b);
};

//main.cpp

#include <A.h>
#include <B.h>

int main()
{
    A a;
    B b;
    a.doStuff(b);
}
0
ответ дан 2 December 2019 в 02:58
поделиться

Не к моему знанию. Это - довольно плохая практика. Я недавно столкнулся с ним с заголовком Windows и некоторым странным интерфейсом в моем коде, все же.

0
ответ дан 2 December 2019 в 02:58
поделиться
Другие вопросы по тегам:

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