CPP 파일에 헤더가 명시 적으로 포함되어 있는지 확인


9

#includeHPP 파일을 통해 이미 포함 된 내용에 관계없이 CPP 파일에 사용 된 모든 유형의 헤더에 대해 일반적으로 좋은 방법이라고 생각 합니다. 나는 수도 그래서 #include <string>내 HPP와 CPP 모두에서, 예를 들어, 난 여전히 컴파일 할 수에도 불구하고 나는 CPP에서 그것을 생략합니다. 이렇게하면 HPP가 전달 선언을 사용했는지 여부에 대해 걱정할 필요가 없습니다.

#include코딩 스타일을 적용 할 수있는 도구가 있습니까? 이 코딩 스타일을 적용 해야합니까 ?

전 처리기 / 컴파일러는 #includeHPP 또는 CPP에서 오는지 신경 쓰지 않기 때문에이 스타일을 따르는 것을 잊어 버린 경우 피드백을받지 못합니다.

답변:


7

이것은 "표준"종류의 코딩 표준이 아닌 "해야한다"중 하나입니다. 그 이유는 C ++ 파서를 작성하여 강제로 작성해야하기 때문입니다.

헤더 파일의 가장 일반적인 규칙은 헤더 파일이 스스로 대기해야한다는 것입니다. 헤더 파일은 해당 헤더를 포함하기 전에 다른 헤더 파일을 #include하는 것을 요구하지 않아야합니다. 이것은 테스트 가능한 요구 사항입니다. 임의의 헤더가 주어지면 foo.hh다음을 컴파일하고 실행해야합니다.

#include "foo.hh"
int main () {
   return 0;
}

이 규칙은 일부 헤더에서 다른 클래스의 사용과 관련하여 결과가 있습니다. 때로는 다른 클래스를 선언하여 이러한 결과를 피할 수 있습니다. 많은 표준 라이브러리 클래스에서는 불가능합니다. std::string또는 과 같은 템플릿 인스턴스화를 전달할 방법이 없습니다 std::vector<SomeType>. 당신에있는 #include유형의 유일한 사용하는 함수에 인수로 경우에도 헤더에 그 STL 헤더.

또 다른 문제는 실수로 끌어서 놓는 것들입니다. 예 : 다음을 고려하십시오.

foo.cc 파일 :

#include "foo.hh"
#include "bar.hh"

void Foo::Foo () : bar() { /* body elided */ }

void Foo::do_something (int item) {
   ...
   bar.add_item (item);
   ...
}

다음 barFoo유형 의 클래스 데이터 멤버입니다 Bar. 여기에서 옳은 일을했고 class를 정의하는 헤더에 포함되어 있어야하지만 #included bar.hh가 있습니다 Foo. 그러나 Bar::Bar()및에 사용 된 내용은 포함하지 않았습니다 Bar::add_item(int). 이러한 호출로 인해 추가 외부 참조가 발생할 수있는 경우가 많습니다.

foo.o와 같은 도구 를 사용 하여 분석 nm하면 해당 함수 foo.cc가 적절하지 않은 모든 종류의 항목을 호출 하는 것처럼 보입니다 #include. 따라서 #include부수적 외부 참조에 대한 지시문을 추가해야 foo.cc합니까? 대답은 절대 아닙니다. 문제는 부수적으로 호출되는 기능과 직접 호출되는 기능을 구별하기가 매우 어렵다는 것입니다.


2

이 코딩 스타일을 적용해야합니까?

아마 아닙니다. 내 규칙은 이것입니다 : 헤더 파일 포함은 순서에 따라 달라질 수 없습니다.

xc에 포함 된 첫 번째 파일이 xh라는 간단한 규칙으로이를 쉽게 확인할 수 있습니다.


1
이것에 대해 자세히 설명해 주시겠습니까? 주문 독립성을 어떻게 확인할 수 있는지 알 수 없습니다.
detly

1
주문 독립성을 보장하지는 않습니다. 단지 #include "x.h"선행을 요구하지 않고 작동 할 수 있도록합니다 #include. 당신이 남용하지 않으면 충분합니다 #define.
케빈 클라인

1
아 알 겠어요 그래도 좋은 생각입니다.
detly

2

특정 헤더 파일이 자체적으로 있어야한다는 규칙을 적용해야하는 경우 이미 보유한 도구를 사용할 수 있습니다. 각 헤더 파일을 개별적으로 컴파일하지만 오브젝트 파일을 생성하지 않는 기본 makefile을 작성하십시오. (C 또는 C ++ 모드)에서 헤더 파일을 컴파일 할 모드를 지정하고 자체 모드를 유지할 수 있는지 확인할 수 있습니다. 출력에 오 탐지가없고 필요한 모든 종속성이 선언되고 출력이 정확하다는 합리적인 가정을 할 수 있습니다.

IDE를 사용하는 경우 IDE에 따라 makefile 없이도이 작업을 수행 할 수 있습니다. 추가 프로젝트를 만들고 확인하려는 헤더 파일을 추가 한 다음 설정을 변경하여 C 또는 C ++ 파일로 컴파일하십시오. 예를 들어 MSVC에서는 "구성 속성-> 일반"의 "항목 유형"설정을 변경합니다.


1

나는 그런 도구가 존재한다고 생각하지 않지만 다른 대답이 나를 반증한다면 기뻐할 것입니다.

이러한 도구를 작성할 때의 문제점은 잘못된 결과를 매우 쉽게보고한다는 것이므로 그러한 도구의 순 이점은 거의 0에 가깝습니다.

이러한 도구가 작동 할 수있는 유일한 방법은 심볼 테이블을 처리 된 헤더 파일의 내용으로 재설정 할 수 있지만 라이브러리의 외부 API를 형성하는 헤더가 실제 선언을 위임하는 문제가 발생하는 것입니다 내부 헤더.
예를 들어, <string>GCC에서 libc ++ 구현은 아무것도 선언하지 않지만 실제 선언을 포함하는 내부 헤더를 포함합니다. 도구가 심볼 테이블을 <string>자체적 으로 선언 한 것으로 재설정하면 아무것도 아닙니다.
도구 #include ""와와를 구분할 수는 #include <>있지만 외부 라이브러리가 #include ""API에 내부 헤더를 포함하는 데 사용 하는 경우에는 도움이되지 않습니다 .


1

#Pragma once이것을 달성 하지 못 합니까? 직접 포함 또는 체인 포함을 통해 원하는만큼 여러 항목을 포함 할 수 있으며, #Pragma once각 항목 옆에있는 한 헤더는 한 번만 포함됩니다.

그것을 시행하는 것에 관해서는, 아마도 컴파일을 보장하기 위해 더미 기본 기능을 가진 각 헤더 자체를 포함하는 빌드 시스템을 만들 수 있습니다. #ifdef체인에는 해당 테스트 방법으로 최상의 결과를 얻을 수 있습니다.


1

항상 CPP 파일에 헤더 파일을 포함하십시오. 이렇게하면 컴파일 시간이 크게 단축 될뿐만 아니라 미리 컴파일 된 헤더를 사용하기로 결정하면 많은 문제가 해결됩니다. 내 경험상, 앞으로 선언하는 데 어려움을 겪는 것조차 연습하는 동안 가치가 있습니다. 필요한 경우에만 규칙을 어기십시오.


이것이 어떻게 "컴파일 시간을 크게 단축시킬 것"인지 설명 할 수 있습니까?
Mawg는 모니카를

1
이를 통해 각 컴파일 단위 (CPP 파일)는 컴파일시 최소 포함 파일 만 가져옵니다. 그렇지 않으면 H 파일에 포함을 넣으면 잘못된 종속성 체인이 빠르게 형성되고 각 컴파일마다 모든 포함을 가져옵니다.
Gvozden

포함 가드를 사용하면 "상당히"의심 할 수 있지만 디스크 액세스 (그러한 고 아드를 발견하기 위해 순서대로)가 "느리게"있다고 가정하면 그 점을 무시할 것입니다. 명확하게 해주셔서 감사합니다
Mawg는 Monica를

0

이 협약에는 장단점이 있습니다. 한편으로 .cpp 파일이 무엇을 포함하는지 정확하게 아는 것이 좋습니다. 반면에, 포함 목록은 우스운 크기로 쉽게 커질 수 있습니다.

이 규칙을 권장하는 한 가지 방법은 헤더에 아무것도 포함하지 않고 .cpp 파일에만 포함시키는 것입니다. 그런 다음 헤더를 사용하는 .cpp 파일은 종속 된 다른 모든 헤더를 명시 적으로 포함하지 않으면 컴파일되지 않습니다.

아마도 여기에 합리적인 타협이있을 것입니다. 예를 들어, 자신의 헤더 안에 표준 라이브러리 헤더를 포함시키는 것이 좋을 수도 있지만 더 이상은 아닙니다.


3
헤더가 포함되지 않은 상태로두면 순서가 중요합니다 ... 그리고 나는 그것을 피하고 싶습니다.
M. Dudley

1
-1 : 종속성 악몽을 만듭니다. xh를 개선하려면 xh가 포함 된 모든 .cpp 파일을 변경해야합니다.
kevin cline

1
@ M.Dudley, 내가 말했듯이 장점과 단점이 있습니다.
Dima
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.