헤더파일 - C/C++ 헤더 파일 순서 포함




헤더파일 컴파일 (7)

파일을 포함시키는 순서는 무엇인가? 즉, 한 헤더를 다른 헤더 앞에 포함시키는 이유는 무엇인가?

예를 들어, 시스템 파일, STL 및 Boost는 로컬 인클루드 파일 전후에 있습니까?


가장 구체적인 것부터 가장 구체적인 것까지 포함하고, .cpp에 해당하는 .hpp가있는 경우 해당 .hpp로 시작하십시오. 그렇게하면, 자급 자족하지 않는 헤더 파일의 숨겨진 의존성이 드러날 것입니다.

이는 미리 컴파일 된 헤더를 사용하면 복잡해집니다. 이 문제를 해결할 수있는 방법 중 하나는 프로젝트 컴파일러에 종속되지 않고 미리 컴파일 된 헤더 포함 파일로 프로젝트 헤더 중 하나를 사용하는 것입니다.


그것은 C / C ++ 세계에서 어려운 문제입니다. 표준 이상의 많은 요소가 있습니다.

나는 헤더 파일의 순서가 컴파일되는 한 심각한 문제가 아니라고 생각한다.

내 생각은 : 모든 헤더에 충돌이 없다면 순서는 괜찮습니다. 결함있는 .h에 #include 줄을 추가하여 머리글 종속성 문제를 해결할 수 있습니다.

일부 헤더가 위의 헤더에 따라 동작을 변경하면 (#if 조건 확인) 실제적인 번거 로움이 발생합니다.

예를 들어, VS2005의 stddef.h에는 다음이 있습니다.

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif

이제 문제 : 많은 사용자 정의 헤더 ( "custom.h")가 시스템 헤더에 offsetof 를 제공하지 않는 일부 컴파일러를 포함하여 많은 컴파일러와 함께 사용해야하는 경우 필자는 헤더에 다음을 작성해야합니다.

#ifndef offsetof
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif

그리고 사용자에게 모든 시스템 헤더 다음에 #include "custom.h" 를 포함하라고 지시하십시오. 그렇지 않으면 stddef.h의 offsetof 줄이 매크로 재정의 오류를 표시합니다.

우리는 더 이상 그런 경우를 만나기를기도하지 않습니다.


나는 다음을 권고한다.

  1. 구축중인 .cc 모듈의 헤더. (프로젝트의 각 헤더에 프로젝트의 다른 헤더에 대한 암시 적 종속성이 없는지 확인하는 데 도움이됩니다.)
  2. C 시스템 파일.
  3. C ++ 시스템 파일.
  4. 플랫폼 / OS / 기타 헤더 파일 (예 : win32, gtk, openGL).
  5. 프로젝트의 다른 헤더 파일.

그리고 물론 각 부분의 알파벳 순서.

헤더 파일에서 불필요한 #include 를 피하려면 항상 forward 선언문을 사용하십시오.


나는 대다수의 문제를 피하는 두 가지 간단한 규칙을 따른다.

  1. 모든 헤더 (실제로 모든 소스 파일)에는 필요한 것을 포함해야합니다. 사용자는 사물을 포함하여 사용자에게 의존해서는 안됩니다 .
  2. 부가 물로서 모든 헤더에는 위의 규칙 1을 지나치게 야심 차게 적용하여 여러 번 포함시키지 않도록 경비원을 포함시켜야합니다.

나는 또한 다음의 지침을 따른다 :

  1. 구분선이있는 시스템 헤더 (stdio.h 등)를 먼저 포함시킵니다.
  2. 그것들을 논리적으로 묶어 라.

다른 말로:

#include <stdio.h>
#include <string.h>

#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"

가이드 라인이긴하지만, 그것은 주관적인 것입니다. 다른 한편으로는, 필자는 경비원을 포함하여 'wrapper'헤더 파일을 include guard와 함께 제공하고 일부 불쾌한 제 3 자 개발자가 내 비전을 구독하지 않는 경우 그룹화 된 내용을 포함합니다 :-)


내 벽돌을 벽에 추가하려면.

  1. 각 헤더는 자급 자족 할 필요가 있습니다. 적어도 한 번 이상 포함 된 경우에만 테스트 할 수 있습니다.
  2. 기호 (매크로, 유형 등)를 도입하여 제 3 자 헤더의 의미를 실수로 수정해서는 안됩니다.

이렇게 나는 보통 이렇게 간다 :

// myproject/src/example.cpp
#include "myproject/example.h"

#include <algorithm>
#include <set>
#include <vector>

#include <3rdparty/foo.h>
#include <3rdparty/bar.h>

#include "myproject/another.h"
#include "myproject/specific/bla.h"

#include "detail/impl.h"

각 그룹은 다음 그룹에서 빈 줄로 구분됩니다.

  • 이 cpp 파일에 처음으로 해당하는 헤더 (온 전성 체크)
  • 시스템 헤더
  • 종속 헤더로 구성된 타사 헤더
  • 프로젝트 헤더
  • 프로젝트 개인 헤더

또한 시스템 헤더와 별도로 각 파일은 네임 스페이스의 이름을 가진 폴더에 있습니다. 왜냐하면 이러한 방식으로 파일을 추적하기가 쉽기 때문입니다.


먼저 .cpp에 해당하는 머리글을 포함하십시오. 즉, source1.cpp 에는 다른 것을 포함하기 전에 source1.cpp 가 포함되어야합니다. 내가 생각할 수있는 유일한 예외는 사전 컴파일 된 헤더가있는 MSVC를 사용할 때 stdafx.h 를 다른 것보다 먼저 포함해야한다는 것입니다.

추론 : 다른 파일보다 먼저 source1.h 를 포함 시키면 의존성없이 단독으로 사용할 수 있습니다. source1.h 가 나중에 종속성을 취하면 컴파일러는 필요한 forward 선언을 source1.h 에 추가하도록 즉시 경고합니다. 이것은 차례로 헤더가 부양 가족에 의해 임의의 순서로 포함될 수 있음을 보장합니다.

예:

source1.h

class Class1 {
    Class2 c2;    // a dependency which has not been forward declared
};

source1.cpp

#include "source1.h"    // now compiler will alert you saying that Class2 is undefined
                    // so you can forward declare Class2 within source1.h
...

MSVC 사용자 : 미리 컴파일 된 헤더를 사용하는 것이 좋습니다. 따라서 표준 헤더 (및 변경하지 않을 다른 헤더)에 대한 모든 #include 지시문을 stdafx.h .


이것은 주관적이지 않습니다. 헤더가 특정 순서로 #include d에 의존하지 않는지 확인하십시오. STL 또는 부스트 헤더를 포함하는 순서는 중요하지 않은지 확인할 수 있습니다.





c