어떤 순서로 파일을 포함시켜야합니까, 즉 한 헤더를 다른 헤더보다 먼저 포함시키는 이유는 무엇입니까?
예를 들어, 시스템 파일, STL 및 Boost가 로컬 포함 파일 이전 또는 이후로 이동합니까?
어떤 순서로 파일을 포함시켜야합니까, 즉 한 헤더를 다른 헤더보다 먼저 포함시키는 이유는 무엇입니까?
예를 들어, 시스템 파일, STL 및 Boost가 로컬 포함 파일 이전 또는 이후로 이동합니까?
답변:
컴파일 된 한 권장 순서가 없다고 생각합니다! 성가신 것은 일부 헤더가 다른 헤더를 먼저 포함해야 할 때입니다. 포함 순서가 아닌 헤더 자체에 문제가 있습니다.
개인적으로 선호하는 것은 지역에서 세계로, 각 하위 섹션을 사전 순으로하는 것입니다.
1.에 대한 나의 이론적 근거는 각 헤더 (cpp가있는)가 #include
전제 조건없이 종료 될 수 있음을 증명해야한다는 것입니다 (터미 너스 테크니 쿠스 : 헤더는 "자체 포함"). 그리고 나머지는 논리적으로 거기에서 흘러 나오는 것 같습니다.
명심해야 할 것은 헤더가 먼저 포함되는 다른 헤더에 의존해서는 안된다는 것입니다. 이를 보장하는 한 가지 방법은 다른 헤더보다 먼저 헤더를 포함시키는 것입니다.
Lakos의 "대규모 C ++ 소프트웨어 디자인"을 참조하여 "C ++로 생각하기"는 특히 이것을 언급합니다.
외부 제공 선언이나 정의없이 구성 요소의 .h 파일이 자체적으로 구문 분석되도록하여 잠재적 사용 오류를 피할 수 있습니다. .h 파일을 .c 파일의 첫 번째 행으로 포함하면 중요한 부분이 없어집니다. 구성 요소의 물리적 인터페이스에 내재 된 정보가 .h 파일에서 누락되었거나 존재하는 경우 .c 파일을 컴파일하려고하면 정보를 찾을 수 있습니다.
즉, 다음 순서로 포함하십시오.
헤더에이 순서에 포함되는 데 문제가있는 경우 헤더를 수정하거나 사용하지 마십시오. 깔끔한 헤더를 작성하지 않는 보이콧 라이브러리.
구글의 C ++ 스타일 가이드는 주장 거의 모두 정말 정당화와, 반대로; 나는 개인적으로 Lakos 접근법을 선호하는 경향이 있습니다.
나는 대부분의 문제를 피하는 두 가지 간단한 규칙을 따릅니다.
또한 다음 지침을 따릅니다.
다시 말해:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
비록 지침이기는하지만 주관적인 것입니다. 반면에 규칙은 난해한 제 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"
각 그룹은 다음 줄과 빈 줄로 구분됩니다.
또한 시스템 헤더와는 별도로 각 파일은 네임 스페이스 이름이있는 폴더에 있습니다. 이러한 방식으로 파일을 쉽게 추적 할 수 있기 때문입니다.
#define
다른 코드를 망칠 수있는 것에 대해 나쁜 것 )과 암시 적 종속성을 방지합니다. 예를 들어, 코드베이스 헤더 파일이 foo.h
실제로 의존 <map>
하지만 .cc
파일 에 사용 된 모든 곳 <map>
에서 이미 포함 된 경우에는 눈치 채지 못할 것입니다. 누군가가 foo.h
먼저 포함하지 않고 포함하려고 할 때까지 <map>
. 그리고 그들은 화가 날 것입니다.
.h
하나 이상 있기 때문입니다 .cpp
(실제로 내 개인 코드에서는 단위 테스트와 관련된 문제가 먼저 포함되며 소스 코드는 올바른 그룹에 포함됨) ). 영향을받지 않는 것과 관련하여 헤더에 포함 <map>
된 경우 이후에 포함 된 모든 헤더가 영향을 받으므로 나에게 싸움을 잃는 것처럼 보입니다.
Header corresponding to this cpp file first (sanity check)
. #include "myproject/example.h"
모든 포함의 끝으로 이동 하면 특별한 것이 있습니까?
나는 추천한다 :
물론 가능하면 각 섹션 내에서 알파벳 순서로 정렬됩니다.
#include
헤더 파일에서 불필요한을 피하려면 항상 선언을 사용 하십시오.
나는 이것이 제정신 세계 어디에서나 권장되는 관행이 아니라고 확신하지만, 시스템 길이를 파일 이름 길이별로 정렬하고 같은 길이 내에서 어휘 적으로 정렬하는 것을 좋아합니다. 이렇게 :
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
포함 순서 종속성의 부끄러움을 피하기 위해 다른 사람들보다 자신의 헤더를 포함시키는 것이 좋습니다.
windows.h
.
먼저 .cpp ...에 해당하는 헤더를 포함하십시오. 즉, 다른 것을 source1.cpp
포함 source1.h
하기 전에 포함 해야 합니다. 내가 생각할 수있는 유일한 예외는 미리 컴파일 된 헤더와 함께 MSVC를 사용할 때입니다.이 경우 stdafx.h
다른 것보다 먼저 포함시켜야 합니다.
추론 :source1.h
다른 파일 이전을 포함하면 파일이 종속되지 않고 독립형 일 수 있습니다. source1.h
나중에 의존성을 취하는 경우 컴파일러는 필요한 전달 선언을 추가하도록 즉시 경고합니다.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
.
C / C ++ 세계에서는 어려운 질문이며 표준을 넘어서는 많은 요소가 있습니다.
squelart가 말한 것처럼 헤더 파일 순서가 컴파일되는 한 심각한 문제는 아니라고 생각합니다.
내 아이디어는 : 모든 헤더에 기호 충돌이 없으면 순서가 정상이며 결함이있는 .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
이제 문제 : offsetof
시스템 헤더에 제공되지 않는 이전 컴파일러를 포함하여 많은 컴파일러와 함께 사용해야하는 사용자 지정 헤더 ( "custom.h")가 있으면 헤더에 작성해야합니다.
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
그리고 모든 시스템 헤더 #include "custom.h"
다음에 사용자에게 알려주십시오 . 그렇지 않으면 offsetof
stddef.h 의 행에 매크로 재정의 오류가 발생합니다.
우리는 경력에서 더 이상 그러한 경우를 만나지 않기를기도합니다.