전달 선언 대 포함


17

Reduce the number of #include files in header files. It will reduce build times. Instead, put include files in source code files and use forward declarations in header files.

나는 이것을 여기에서 읽었다. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html .

따라서 헤더 파일의 클래스 (클래스 A)가 일부 클래스 (클래스 B)의 실제 정의를 사용할 필요가 없다고 말합니다. 이때 특정 (클래스 B) 헤더 파일을 포함하는 대신 정방향 선언을 사용할 수 있습니다.

질문 : 헤더의 클래스 (클래스 A)가 특정 클래스 (클래스 B)의 실제 정의를 사용하지 않으면 컴파일 선언 시간을 줄이는 데 어떻게 앞으로 선언이 도움이됩니까?

답변:


11

컴파일러는 클래스 A가 클래스 B를 사용하는지 신경 쓰지 않습니다. 클래스 A가 컴파일되고 클래스 B의 사전 선언이없는 경우 (포워드 선언 등) 패닉이 발생하여 오류로 표시됩니다.

여기서 중요한 것은 고양이가 키보드를 밟은 후 프로그램을 컴파일하지 않았다는 것을 컴파일러가 알고 클래스로 해석되거나 해석되지 않는 임의의 문자를 만든 것입니다.

포함을 볼 때 포함 된 정보를 사용하려면 파일을 열고 구문 분석해야합니다 (실제로 수행해야하는지 여부에 관계없이). 해당 파일에 다른 파일이 포함 된 경우 해당 파일도 열고 구문 분석해야합니다.이를 피할 수있는 경우 일반적으로 전달 선언을 대신 사용하는 것이 좋습니다.

편집 : 이 규칙의 예외는 미리 컴파일 된 헤더입니다. 이 경우 모든 헤더는 향후 컴파일을 위해 컴파일 및 저장됩니다. 헤더가 변경되지 않으면 컴파일러는 이전 컴파일에서 사전 컴파일 된 헤더를 지능적으로 사용하여 컴파일 시간을 단축 할 수 있지만 헤더를 자주 변경할 필요가없는 경우에만 잘 작동합니다.


설명 주셔서 감사합니다. 그런 다음 확인을 예를 들어 세 개의 헤더 파일이 있다고 생각합니다 vehicle.h, bus.h, toybus.h. vehicle.h에 의해 포함 bus.h및에 의해 bus.h포함 toybus.h. 나는 몇 가지 변화를 할 경우 너무 bus.h. 컴파일러가 열리고 vehicle.h다시 구문 분석 됩니까? 다시 컴파일합니까?
Nayana Adassuriya

1
@NayanaAdassuriya 예, 매번 포함 및 구문 분석되므로 헤더 파일에서 선언을 #pragma once보거나 #ifndef __VEHICLE_H_입력하여 이러한 파일이 여러 번 포함되는 것을 방지합니다 (적어도 ifndef의 경우에는 여러 번 사용되지 않음).
Neil

4

왜냐하면 A.hpp는 B.hpp를 #include 할 필요가 없기 때문입니다.

그래서 A.hpp는

class B;//or however forward decl works for classes

class A
{
    B* bInstance_;
//...
}

따라서 A.hpp가 포함되면 B.hpp는 암시 적으로 포함되지 않으며 A.hpp에만 의존하는 모든 파일은 b.hpp가 변경 될 때마다 다시 컴파일 할 필요가 없습니다.


소스 파일 (A.cpp)에 있습니다. 실제 헤더 파일 (Bh)을 포함해야합니다. 따라서 컴파일해야 할 때마다. 마지막으로 Bh는 변경 사항으로 Bh를 다시 컴파일해야합니다. 다른가요?
Nayana Adassuriya

A는 B에 대한 포인터 만 사용하고 B로 변경해도 A.hpp (또는 포함 된 파일)에는 영향을 미치지 않으므로 @NayanaAdassuriya no
ratchet freak

@ NayanaAdassuriya : 그렇습니다 .A.cpp는 다시 컴파일해야합니다 (A의 메소드 본문 내에서 B의 정의를 사용하지만 일반적으로 수행하는 경우).하지만 A를 사용하지만 B는 직접 사용하지 않는 C.cpp는 그렇지 않습니다.
Jan Hudec

3

C / C ++ 전처리 기는 별도의 텍스트 처리 단계입니다. #include포함 된 헤더의 내용의 지시문을 가져오고 컴파일러를 구문 분석 할 수있다. 또한 각각의 컴파일 .cpp은 완전히 분리되어 있으므로 B.h컴파일 할 때 컴파일러가 구문 분석했다는 사실은 컴파일 B.cpp할 때 다시 필요할 때 가장 도움이되지 않습니다 A.cpp. 그리고 다시 컴파일 할 때 C.cpp. 그리고 D.cpp. 등등. 파일에 포함 된 파일이 변경된 경우 해당 파일 각각을 다시 컴파일해야합니다.

클래스 A가 클래스 B와 클래스 CD사용 하고 클래스 를 사용 A하지만 조작 할 필요는 없다고 가정 해보십시오 B. 클래스는 경우 A단지 앞으로 선언으로 선언 할 수 있습니다 B보다, B.h컴파일 할 때 : 두 번 컴파일 B.cpp하고 A.cpp(때문에 B여전히 내부 필요 A의 방법).

그러나 A.h포함 B.h, 컴파일 컴파일 할 때 시간이- B.cpp, A.cpp, C.cppD.cpp(가) 나중에이 지금 간접적으로 포함으로 B.h도.

또한 헤더가 두 번 이상 포함 된 경우에도 전처리 기는 여전히 매번 헤더를 읽어야합니다 . 보호 때문에 내용 처리를 건너 뛰지 #ifdef만 여전히 읽고 가드 끝을 검색해야하므로 내부의 모든 전 프로세서 지시문을 구문 분석해야합니다.

(다른 답변에서 언급했듯이 미리 컴파일 된 헤더는이 문제를 해결하려고 시도하지만 자체 웜 캔입니다. 기본적으로 시스템 헤더에 합리적으로 사용할 수 있으며 너무 많이 사용하지 않는 경우에만 사용할 수 있습니다 프로젝트의 헤더)


+1, 헤더 포함은 클래스 A와 B가 두 개가 아닌 상당히 많은 클래스가있을 때 심각한 문제가됩니다. 다른 모든 게시물은 그 중심점을 놓친 것 같습니다.
Doc Brown

2

정방향 선언은 더 많은 헤더 파일을 포함 할 수있는 전체 헤더 파일보다 구문 분석이 훨씬 빠릅니다.

또한 클래스 B의 헤더 파일에서 무언가를 변경하면 해당 헤더를 포함한 모든 것을 다시 컴파일해야합니다. 앞으로 선언하면 A의 구현이 상주하는 소스 파일 일 수 있습니다. 그러나 A의 헤더에 실제로 B의 헤더가 포함 된 경우 B를 a.hpp사용하지 않더라도 모든 것을 다시 컴파일합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.