헤더 파일이 실제로 좋습니까? [닫은]


20

C ++ 소스 파일을 탐색 할 때 클래스 파일의 모든 함수와 데이터 멤버에 대한 "요약"을 제공하기 때문에 헤더 파일이 유용하다는 것을 알았습니다. 왜 루비, 파이썬, 자바 등과 같은 다른 언어들도 이와 같은 기능을 가지고 있지 않습니까? 이것이 C ++의 자세한 정보가 유용한 영역입니까?


저는 C와 C ++의 도구에 익숙하지 않지만 제가 작업 한 대부분의 IDE / 코드 편집기는 "구조"또는 "개요"보기를 가지고 있습니다.
Michael K

1
헤더 파일이 좋지 않습니다-필요합니다!
Pete

답변:


31

헤더 파일의 원래 목적은 C에서 단일 패스 컴파일 및 모듈화를 허용하는 것이 었습니다. 사용하기 전에 메서드를 선언하여 단일 컴파일 패스 만 허용했습니다. 강력한 컴퓨터가 아무 문제없이 멀티 패스 컴파일을 수행 할 수 있고 때로는 C ++ 컴파일러보다 빠르기 때문에이 시대는 오래 걸렸습니다.

C와 C가 하위 호환성을 유지하려면 헤더 파일을 유지해야하지만 그 위에 많은 부분이 추가되어 상당히 문제가있는 디자인이되었습니다. FQA 에서 더 많은 것 .

모듈화를 위해서는 모듈의 코드에 대한 메타 데이터로 헤더 파일이 필요했습니다. 예 : 어떤 라이브러리에서 사용할 수있는 메소드 (및 C ++ 클래스) 컴파일 시간이 많이 걸리기 때문에 개발자가 이것을 작성하는 것이 분명했습니다. 요즘 컴파일러가 코드 자체에서이 메타 데이터를 생성하도록하는 것은 문제가되지 않습니다. Java 및 .NET 언어는이 작업을 정상적으로 수행합니다.

그래서 안돼. 헤더 파일이 좋지 않습니다. 그들은 우리가 여전히 별도의 플로피에 컴파일러와 링커를 가지고 있었고 컴파일에는 30 분이 걸렸습니다. 요즘에는 방해가되고 디자인이 잘못되었습니다.


8
나는 당신이 쓰는 대부분의 내용에 동의하지만, 마지막 단락은 일을 조금 간단하게 만듭니다. 헤더 파일은 여전히 ​​공용 인터페이스를 정의하는 데 유용한 목적을 제공합니다.
Benjamin Bannier

3
@honk 그게 내 질문으로 얻은 것입니다. 그러나 현대 IDE (ElYusubov가 제안한)가 이것을 부정한다고 생각합니다.
Matt Fichman

5
C ++위원회가 모듈에 대해 작업 중이므로 헤더없이 또는보다 효율적인 방식으로 사용되는 헤더를 사용하여 C 및 C ++를 사용할 수 있습니다. 그러면이 답변이 더 공정해질 것입니다.
Klaim

2
@MattFichman : 일부 헤더 파일을 생성하는 것은 하나의 일이지만 (대부분의 프로그래머 편집자 / IDE는 어떤 방식 으로든 자동으로 수행 할 수 있음) 공개 API에 대한 요점은 실제 사람이 효과적으로 정의하고 설계해야한다는 것입니다.
Benjamin Bannier

2
@honk 예. 그러나 이것을 별도의 파일로 정의 할 이유는 없습니다. 구현과 동일한 코드 일 수 있습니다. C # 이하는 것처럼.
Euphoric

17

그것들이 문서 형식으로 유용 할 수 있지만 헤더 파일을 둘러싼 시스템은 매우 비효율적입니다.

C는 각 컴파일 패스가 단일 모듈을 빌드하도록 설계되었습니다. 각 소스 파일은 별도의 컴파일러 실행으로 컴파일됩니다. 반면에 헤더 파일은이를 참조하는 각 소스 파일에 대해 해당 컴파일 단계에 삽입됩니다.

즉, 헤더 파일이 300 개의 소스 파일에 포함 된 경우 프로그램을 빌드하는 동안 300 번의 별도 횟수로 구문 분석 및 컴파일됩니다. 똑같은 결과가 반복되는 똑같은 것. 이것은 엄청난 시간 낭비이며 C 및 C ++ 프로그램을 빌드하는 데 오랜 시간이 걸리는 주된 이유 중 하나입니다.

모든 현대 언어는 의도적 으로이 터무니없는 비 효율성을 피합니다. 대신 일반적으로 컴파일 된 언어로 필요한 메타 데이터가 빌드 출력 내에 저장되어 컴파일 된 파일이 컴파일 된 파일에 포함 된 내용을 설명하는 일종의 빠른 조회 참조로 작동 할 수 있습니다. 헤더 파일의 모든 이점은 추가 작업없이 자동으로 생성됩니다.

인터프리터 언어로 또는로드 된 모든 모듈은 메모리에 남아 있습니다. 라이브러리를 참조하거나 포함하거나 요구하면 관련 소스 코드를 읽고 컴파일하여 프로그램이 끝날 때까지 상주합니다. 다른 곳에도 필요한 경우 이미로드 된 추가 작업이 없습니다.

두 경우 모두 언어 도구를 사용하여이 단계에서 생성 된 데이터를 "찾아 볼"수 있습니다. 일반적으로 IDE에는 일종의 클래스 브라우저가 있습니다. 언어에 REPL이 있으면로드 된 객체의 문서 요약을 생성하는 데 종종 사용될 수도 있습니다.


5
엄격히 사실이 아님-대부분의 컴파일러는 헤더를 다음 컴파일 단위에 포함시키는 것으로 헤더를 미리 컴파일하여 미리 컴파일 된 코드 블록을 찾는 것보다 나쁘지 않습니다. 예를 들어 .NET 코드는 컴파일하는 모든 C # 파일에 대해 system.data.types를 반복적으로 '빌딩'하는 것과 다릅니다. C / C ++ 프로그램이 너무 오래 걸리는 이유는 실제로 컴파일 (및 최적화)되기 때문입니다. .NET 프로그램에 필요한 모든 것은 IL로 구문 분석되어야하며 런타임은 JIT를 통해 실제 컴파일을 수행합니다. 즉, C # 코드의 300 소스 파일도 컴파일하는 데 시간이 오래 걸립니다.
gbjbaanb

7

기능 및 데이터 멤버에 대한 파일을 찾아 보면 무슨 의미인지 명확하지 않습니다. 그러나 대부분의 IDE는 찾아보기위한 도구를 제공합니다 는 클래스 하고 클래스 데이터 멤버 합니다.

예를 들면 : 비주얼 스튜디오가 가지고 Class ViewObject browser그 잘 요청한 기능을 제공합니다. 다음 스크린 샷과 같이.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


4

헤더 파일의 또 다른 단점은 프로그램이 포함 순서에 따라 달라지며 프로그래머가 정확성을 보장하기 위해 추가 단계를 수행해야한다는 것입니다.

이는 C의 매크로 시스템 (C ++에서 상 속됨)과 결합하여 많은 함정과 혼란스러운 상황을 초래합니다.

예를 들어, 하나의 헤더가 매크로를 사용하여 일부 심볼을 ​​정의하고 다른 헤더가 함수 이름과 같은 다른 방식으로 심볼을 사용한 경우 포함 순서는 최종 결과에 큰 영향을 미칩니다. 그러한 예가 많이 있습니다.


2

헤더 파일은 클래스 변수와 같은 추가 정보와 함께보기 쉬운 하나의 파일에 구현에 대한 인터페이스 형식을 제공하기 때문에 항상 좋아했습니다.

클래스 당 2 개의 파일을 사용하여 작성된 많은 C # 코드 (클래스 당 2 개의 파일이 필요하지 않음)가 있습니다. 하나는 실제 클래스 구현이고 다른 하나는 인터페이스가 있습니다. 이 디자인은 조롱 (일부 시스템에서는 필수적)에 적합하며 컴파일 된 메타 데이터를보기 위해 IDE를 사용할 필요없이 클래스의 문서를 정의하는 데 도움이됩니다. 좋은 연습을하기 위해 지금까지갔습니다.

따라서 C / C ++는 헤더 파일에서 동등한 인터페이스를 요구하는 것이 좋습니다.

나는 '2 개의 파일에 물건을 넣어야하는 경우 코드를 해킹하는 것이 더 어렵다'는 것을 포함하여 다른 시스템의 지지자들이 있다는 것을 알고 있지만 코드를 해킹하는 것은 어쨌든 좋은 습관이 아니라고 생각합니다. 좀 더 생각하고 코드를 작성 / 디자인하기 시작하면 당연히 헤더 / 인터페이스를 정의하게됩니다.


다른 파일의 인터페이스 및 구현? 의도적으로 이것을 설계해야하는 경우 하나의 파일에서 Java / C #와 같은 언어로 인터페이스 (또는 추상 클래스)를 정의하고 다른 파일에서 구현을 숨기는 것이 매우 일반적입니다. 오래되고 까다로운 헤더 파일이 필요하지 않습니다.
Petter Nordlander

뭐라고? 내가 말한 것이 아닙니다-인터페이스와 클래스 구현을 2 개의 파일로 정의하십시오.
gbjbaanb

2
글쎄, 그것은 헤더 파일을 필요로하지 않으며 헤더 파일을 더 잘 만들지 않습니다. 예, 레거시가있는 언어에서는 필요하지만 개념으로 인터페이스 / 구현을 다른 파일로 분할 할 필요는 없습니다 (실제로 악화시킵니다).
Petter Nordlander

@ Peter 나는 당신이 오해한다고 생각합니다. 개념적으로 다르지 않습니다. 헤더는 C 언어로 인터페이스를 제공하기 위해 존재하며, 옳습니다.하지만 2 (헤더 전용 C 코드와 마찬가지로)를 결합 할 수는 없습니다. 내가 본 모범 사례는 여러 곳에서 이어졌습니다. 예를 들어 내가 본 모든 C # 개발자는 인터페이스를 클래스에서 분리했습니다. 인터페이스 파일을 여러 개의 다른 파일에 오염없이 포함시킬 수 있으므로이를 수행하는 것이 좋습니다. 이 분할이 최선의 방법이라고 생각하면 C에서 분할하는 방법은 헤더 파일을 사용하는 것입니다.
gbjbaanb

헤더가 인터페이스와 구현을 분리하는 데 실제로 유용한 경우 개인 구성 요소를 숨기고 최종 사용자가 다시 컴파일하지 않아도되도록 PImpl과 같은 것이 필요하지 않습니다. 대신, 우리는 두 세계에서 최악의 상황을 겪습니다. 헤더는 신속하게 해체 된 파사드 외관을 피하면서 무수히 많은 함정을 열며, 해결해야 할 경우 자세한 보일러 플레이트 코드가 필요합니다.
underscore_d

1

실제로 헤더 파일은 인터페이스와 구현을 혼란스럽게하기 때문에 좋지 않습니다. 일반적으로 프로그래밍, 특히 OOP의 의도는 정의 된 인터페이스를 갖고 구현 세부 사항을 숨기는 것이지만 C ++ 헤더 파일은 메소드, 상속 및 공용 멤버 (인터페이스)와 개인용 메소드 및 개인용 멤버를 모두 표시합니다. (구현의 일부). 말할 필요도없이 헤더 파일에 코드 또는 생성자를 인라인하고 일부 라이브러리에는 헤더에 템플릿 코드가 포함되어 구현과 인터페이스가 실제로 혼합되어 있습니다.

원래 의도는 코드가 스크립트의 전체 내용을 가져 오지 않고도 다른 라이브러리, 객체 등을 사용할 수 있도록하는 것이 었습니다. 컴파일하고 링크 할 헤더 만 있으면됩니다. 그런 식으로 시간과 사이클을 절약합니다. 이 경우에는 괜찮은 아이디어이지만 이러한 문제를 해결하는 한 가지 방법 일뿐입니다.

프로그램 구조를 탐색하는 데있어 대부분의 IDE는 이러한 기능을 제공하며 인터페이스를 시작하고 코드 분석, 디 컴파일 등을 수행 할 수있는 많은 도구가 있으므로 덮개 아래에서 무슨 일이 일어나고 있는지 확인할 수 있습니다.

다른 언어가 동일한 기능을 구현하지 않는 이유는 무엇입니까? 글쎄, 다른 언어는 다른 사람들로부터 왔고, 그 디자이너 / 창조자들은 일이 어떻게 작동해야하는지에 대한 다른 비전을 가지고 있습니다.

가장 좋은 대답은해야 할 일을 고수하고 행복하게 만드는 것입니다.


0

많은 프로그래밍 언어에서 프로그램을 여러 컴파일 단위로 세분화 할 때 컴파일러에 어떤 것이 있는지 아는 수단이있는 경우 한 단위의 코드는 다른 단위로 정의 된 것을 사용할 수 있습니다. 하나의 컴파일 단위를 처리하는 컴파일러가 현재 단위 내에서 사용되는 모든 것을 정의하는 모든 컴파일 단위의 전체 텍스트를 검사하도록 요구하는 대신, 컴파일러가 각 단위를 처리하는 동안 함께 컴파일되는 단위의 전체 텍스트를 수신하도록하는 것이 가장 좋습니다. 다른 모든 사람들의 작은 정보로.

C에서 프로그래머는 각 단위에 대해 두 개의 파일을 작성해야합니다. 하나는 해당 단위를 컴파일 할 때만 필요한 정보를 포함하고 다른 하나는 다른 단위를 컴파일 할 때 필요한 정보를 포함합니다. 이것은 다소 불쾌하고 해킹적인 디자인이지만 컴파일러가 중간 파일을 생성하고 처리하는 방법에 대한 언어 표준을 지정할 필요가 없습니다. 다른 많은 언어들은 다른 접근 방식을 사용하는데, 컴파일러는 각 소스 파일에서 외부 코드에 액세스 할 수있는 소스 파일의 모든 내용을 설명하는 중간 파일을 생성합니다. 이 방법을 사용하면 두 개의 소스 파일에 중복 정보가 없어도되지만 컴파일 플랫폼에서는 C에 필요하지 않은 방식으로 파일 의미를 정의해야합니다.

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