2009-12-23 4 views
3

모든 헤더를 보호한다고 가정 할 때 추상적 인 데이터 유형이 있다고 가정 해 보겠습니다.다른 헤더에 포함 된 헤더에 의존해야합니까?

#include "that.h" 
#include "there.h" 

class Foo { 
protected: 
    // Functions that do stuff with varOne and varTwo 
private: 
    that varOne; 
    there varTwo; 
... 
}; 

그리고 foo는 상속 클래스에 당신은 또한이 포함 귀찮게 것, (따라서 foo.h 포함)? 일반적으로 내가하는 일은 클래스가 필요로하는 모든 것을 포함하는 것입니다. 중복인가?

답변

3

직접적으로 포함 된 헤더 파일을 중복해서 포함하는 단점이 있습니다. 컴파일러가 강제로 다시 열어 다시 보급하도록합니다. 예를 들어,에서

아 :

#ifndef __A_H 
#define __A_H 
// whatever 
#endif 

BH :

#ifndef __B_H 
#define __B_H 
#include "a.h" 
// whatever 
#endif 

c.cpp :

#include "a.h" 
#include "b.h" 
//whatever 

아 열 두 번을 읽을 수있다 - 비록 #ifndef은 두 번째 inc에서 prepro가 아의 내용을 무시하도록합니다. lusion을 실행하려면 적어도 디스크에서 파일을로드하고 #ifndef에서 #endif으로 바이트를 읽어야합니다.

이렇게하면 컴파일 속도가 느려질 수 있습니다. 그것은 빌드 나 다른 것을 해치지 않을 것입니다. 컴파일이 많은 시간이 걸릴 수있는 정말로 큰 프로젝트에서 성가 시게 될 것입니다.

헤더에 #pragma once을 사용하면 인식 컴파일러가 파일 이름을 상위 레벨에서 캐시 할 수 있고 두 번째로 a.h를 모두 포함하지 않을 가능성이 있습니다. 그것도 빌드 속도를 높일 수 있습니다.

+0

감사합니다. 나는 이것을 고려했다. 그러나 그것의 독서가 편집을 상당히 늦출 것이라고 생각하지 않았다. – Anonymous

+0

gcc 및 다른 컴파일러가 헤더 파일을 캐시하고 include guard를 자동으로 인식 할 수 있다고 들었습니다 (http://www.efnetcpp.org/wiki/Include_guards). 이것에 대한 성능 저하는 거의 없을 것입니다. –

+0

프로젝트 크기에 따라 다릅니다. 컴파일하는 데 2 ​​분이 걸리면 차이를 느끼지 못할 것입니다. 우리는 매년 # include-dependency-spring-cleaning을 진행합니다.이 클리닝은 30 분의 재건 중 5-10 분을 면도합니다. 어떤 사람들은 심지어 한 발 더 나아간다고 들었습니다. 말하자면, 300 개의 .cpp 파일을 컴파일하고 연결 한 다음, # 50 개의 파일을 포함하는 6 개의 .cpp 파일이 있기 때문에 컴파일러는 더 적은 단위로.그들은 컴파일 시간을 절반으로 줄 였지만, 우리의 경우 컴파일러의 기억을 날려 버렸습니다. – Crashworks

0

정말 대단합니다. 수퍼 클래스가 헤더를 포함하지 않는다는 것이 확실하다면 #include을 생략하는 것이 좋습니다. 물론, 당신은 그냥 안전을 위해 추가 할 수 있습니다.

+0

감사합니다. 나는 그것이 큰 거래라고 생각하지 않았다. 그것에 대해 어떤 유효한 논쟁이 있었 더라면 관심이 있었다. 보이지 않는 것 같습니다. – Anonymous

0

반드시 중복되는 것은 아닙니다. 별도의 헤더 파일과 소스 파일이 있다는 것은 소스 파일이 헤더 파일에 대한 정의를 제공하는 한 src와 헤더 파일을 서로 바꿀 수 있다는 것을 의미합니다.

.h 파일에는 헤더에 사용 된 사항 만 포함되어야합니다. 헤더에 io 선언이 없다면 예를 들어 stdio가 필요하지 않습니다. 대신 printf를 사용하는 경우에는 src 파일에만 있어야합니다.

그러나 사용할 수있는 헤더 하나가 특정 인클루드를 필요로하는 반면 다른 헤더는 그렇지 않은 경우가있을 수 있습니다 (예 : 하나의 헤더가 다른 헤더보다 더 제한적인 인터페이스 일 때). .h가 포함됩니다.

당신이 제작하는 최종 개체/exe에는 아무런 차이가 없으므로 걱정할 필요가있는 부분은 컴파일 시간이 늘어나지 않으므로, 컴파일 타임을 늘릴 필요가있을 때를 대비하여 포함하는 것이 좋습니다. 어떤 시점에서 다른 .h 파일.

편집 : 더 구체적인 예 inc1.h

#ifndef INC1_H 
#define INC1_H 
inc1_struct {                
    int x; 
}; 
#endif 

inc2.h

#ifndef INC2_H 
#define INC2_H 
#include "inc1.h" 
void inc2_f(); 
struct inc1_struct *inc2_callinc1(); 
#endif 

prog.cpp 사용법 #include "inc1.h" 사용법 #include "inc2.h"
#INCLUDE 사용법 #include

void inc2_f() { 
    printf("inc2_f\n"); 
} 

struct inc1_struct *inc2_callinc1() { 
    return (struct inc1_struct*) malloc(sizeof(struct inc1_struct)); 
} 

int main(int argc, char **argv) { 
    struct inc1_struct *s = inc2_callinc1(); 
    return 0; 
} 

이 컴파일,하지만 당신은 노출하지 않으려는 말할 수 것

그런 다음 inc2.h 파일에 inc1.h을 포함 할 필요가 없습니다 inc2.h

에서

struct inc1_struct *inc2_callinc1(); 

, 그러나 prog.cpp에서 inc2_callinc1() 정의를 삭제하지 않으려면 inc1.h를 포함해야합니다.

1

필자의 경험에 따르면, Foo.h에는 선언문을 전달하는 것이 기술적으로 필요하지 않기 때문에 Foo.h에 선언문을 포함하는 대신 전달하는 것이 좋습니다. foo는 상속 클래스에 다음

class that; 
class there; 

class Foo 
{ 
    public: 

     void func(that &param) = 0; 
     void funcTwo(there &param) = 0; 
     ... 
}; 
+0

감사합니다. 벙어리 실수, 나는 조금 더 현실적인 예를 만들거야. – Anonymous

0

(따라서 foo를 포함 : 그 케이드에서

는 Foo.h과 같을 것이다.h), 도 포함하여 귀찮게하고 이 있습니까?

일반적으로 헤더에서 직접 사용하는 모든 유형의 헤더 (경비원 포함)가 포함됩니다.

그러나, 나는 종종 드롭이 기본 클래스 해야 때문에 무시하는 멤버 함수 프로토 타입을 포함 한 파생 클래스 - 사실 에 대한 예 그.

궁극적으로 선택 사항이지만 머리 글자가 실제로 변경 될 가능성이 얼마나 큰지 고려해 볼 수 있습니다.

1

문제는 당신이 이런 식으로 obj 파일에 여분의 것들을 포함하는 것입니다. 헤더 가드는 이것을 막지 않습니다. 참조하는 것은 객체에 있어야하므로 다른 헤더를 포함하여 많은 헤더를 포함하지 말고 다른 헤더를 포함하십시오. 헤더가 엉망이고 많은 파일을 가지고 있다면 빠르게 코드 크기가 커지고 컴파일 시간이 느려집니다.

관련 문제