코드를 여러 파일로 나눌 때 정확히 .h 파일에 들어가야하는 것과 .cpp 파일에 들어가야하는 것은 무엇입니까?
.hpp
C 선언은 .h
파일에 들어가고 C 선언은 파일에 들어간다고 생각 합니다. 이는 C와 C ++ 코드를 혼합 할 때 매우 유용합니다 (예 : C의 레거시 모듈).
코드를 여러 파일로 나눌 때 정확히 .h 파일에 들어가야하는 것과 .cpp 파일에 들어가야하는 것은 무엇입니까?
.hpp
C 선언은 .h
파일에 들어가고 C 선언은 파일에 들어간다고 생각 합니다. 이는 C와 C ++ 코드를 혼합 할 때 매우 유용합니다 (예 : C의 레거시 모듈).
답변:
헤더 파일 ( .h
)은 여러 파일에 필요한 정보를 제공하도록 설계되었습니다. 클래스 선언, 함수 프로토 타입 및 열거와 같은 것은 일반적으로 헤더 파일에 들어갑니다. 한마디로 "정의".
코드 파일 ( .cpp
)은 하나의 파일에서만 알아야하는 구현 정보를 제공하도록 설계되었습니다. 일반적으로 다른 모듈에서 액세스해야하거나 절대로 액세스하지 않을 함수 본문 및 내부 변수는 .cpp
파일에 속합니다 . 한마디로 "구현".
자신에게 무엇이 속하는지 스스로에게 물어 보는 가장 간단한 질문은 "이것을 변경하면 다시 컴파일되도록 다른 파일의 코드를 변경해야합니까?"입니다. 대답이 "예"이면 헤더 파일에있을 수 있습니다. 대답이 "아니오"이면 아마도 코드 파일에있을 것입니다.
export
). # 1 주변의 유일한 방법은 PIMPL입니다. # 2 export
는 지원되는 경우 가능하며 C ++ 0x 및 extern
템플릿을 사용하여 가능할 수 있습니다 . IMO, C ++의 헤더 파일은 많은 유용성을 잃습니다.
사실, C ++에서 이것은 C 헤더 / 소스 조직보다 다소 복잡합니다.
컴파일러는 헤더가 제대로 포함 된 하나의 큰 소스 (.cpp) 파일을 봅니다. 소스 파일은 개체 파일로 컴파일되는 컴파일 단위입니다.
한 컴파일 단위에 다른 컴파일 단위의 구현에 대한 정보가 필요할 수 있기 때문입니다. 예를 들어 한 소스에서 함수의 구현을 작성하고이를 사용해야하는 다른 소스에서이 함수의 선언을 작성할 수 있습니다.
이 경우 동일한 정보의 사본이 두 개 있습니다. 어느 것이 악 ...
해결책은 몇 가지 세부 사항을 공유하는 것입니다. 구현은 소스에 남아 있어야하지만 함수와 같은 공유 심볼의 선언이나 구조, 클래스, 열거 형 등의 정의는 공유해야 할 수 있습니다.
헤더는 공유 된 세부 정보를 입력하는 데 사용됩니다.
여러 소스간에 공유해야하는 항목의 선언을 헤더로 이동
C ++에는 공유가 필요하기 때문에 헤더에 넣을 수있는 다른 것들이 있습니다.
공유 구현을 포함하여 공유해야 할 모든 것을 헤더로 이동
예. 사실, "헤더"안에있을 수있는 많은 다른 것들이 있습니다 (즉, 소스간에 공유 됨).
복잡해지고 어떤 경우에는 (심볼 간의 순환 종속성) 하나의 헤더에 보관할 수 없습니다.
즉, 극단적 인 경우 다음을 수행 할 수 있습니다.
템플릿 MyObject가 있다고 가정 해 봅시다. 우리는 다음을 가질 수 있습니다.
// - - - - MyObject_forward.hpp - - - -
// This header is included by the code which need to know MyObject
// does exist, but nothing more.
template<typename T>
class MyObject ;
.
// - - - - MyObject_declaration.hpp - - - -
// This header is included by the code which need to know how
// MyObject is defined, but nothing more.
#include <MyObject_forward.hpp>
template<typename T>
class MyObject
{
public :
MyObject() ;
// Etc.
} ;
void doSomething() ;
.
// - - - - MyObject_implementation.hpp - - - -
// This header is included by the code which need to see
// the implementation of the methods/functions of MyObject,
// but nothing more.
#include <MyObject_declaration.hpp>
template<typename T>
MyObject<T>::MyObject()
{
doSomething() ;
}
// etc.
.
// - - - - MyObject_source.cpp - - - -
// This source will have implementation that does not need to
// be shared, which, for templated code, usually means nothing...
#include <MyObject_implementation.hpp>
void doSomething()
{
// etc.
} ;
// etc.
"실생활"에서는 일반적으로 덜 복잡합니다. 대부분의 코드에는 소스에 일부 인라인 코드가 포함 된 단순한 헤더 / 소스 구성 만 있습니다.
그러나 다른 경우 (서로 알고있는 템플릿 객체)에서는 컴파일 오류를 확인하는 데 도움이되도록 해당 헤더를 포함하는 빈 소스와 함께 각 객체에 대해 별도의 선언 및 구현 헤더를 가져야했습니다.
헤더를 별도의 헤더로 나누는 또 다른 이유는 컴파일 속도를 높이고, 필요에 따라 파싱되는 심볼의 수를 제한하고, 인라인 메서드 구현이 변경되었을 때 포워드 선언 만 신경 쓰는 소스의 불필요한 재 컴파일을 피하는 것입니다.
코드 구성은 가능한 한 단순하고 가능한 모듈 식으로 만들어야합니다. 소스 파일에 가능한 많이 넣으십시오. 공유해야하는 항목 만 헤더에 노출하십시오.
그러나 템플릿 객체간에 순환 종속성이있는 날에는 코드 구성이 일반 헤더 / 소스 구성보다 "흥미 롭다"고해서 놀라지 마십시오.
^ _ ^
다른 모든 답변 외에도 헤더 파일에 넣지 말아야 할 내용을 알려 드리겠습니다.
using
선언 (가장 일반적인 존재 using namespace std;
)은 포함 된 소스 파일의 네임 스페이스를 오염 시키므로 헤더 파일에 나타나지 않아야합니다. .
using
헤더의 전역 네임 스페이스로 물건을 가져 오는 데 사용하지 마십시오 .
static inline
는 내부 연결을 템플릿과 결합 할 때 발생하는 일과 관련이 있기 때문에 C99에서 사용하는 경우 C ++에서 권장됩니다 . Anon 네임 스페이스를 사용하면 외부 연결을 유지하면서 기능을 "숨길"수 있습니다.
무엇 아무것도로 컴파일 (영 진 풋 프린트) 헤더 파일로 들어갑니다.
변수는 아무것도 컴파일되지 않지만 유형 선언은 수행합니다 (변수가 작동하는 방식 만 설명하므로).
함수는 그렇지 않지만 인라인 함수는 호출 된 위치에서만 코드를 생성하기 때문에 수행합니다 (또는 매크로).
템플릿은 코드가 아니라 코드를 만드는 방법 일뿐입니다. 그래서 그들은 또한 h 파일로 이동합니다.
일반적으로 헤더 파일에는 선언을, 구현 (.cpp) 파일에는 정의를 넣습니다. 이에 대한 예외는 정의가 헤더에 있어야하는 템플릿입니다.
이 질문과 이와 유사한 질문은 자주 묻는 질문 입니다. C ++에 헤더 파일과 .cpp 파일이있는 이유를 참조하십시오 . 및 C ++ 헤더 파일, 코드 분리 예.
주로 헤더 파일에는 클래스 스켈레톤 또는 선언이 포함됩니다 (자주 변경되지 않음).
cpp 파일에는 클래스 구현이 포함되어 있습니다 (자주 변경됨).
나는 기대한다 :
하지만 정말 답은 넣지 말아야 할 것입니다.
헤더 정의 무언가를 하지만 구현에 대해 알려주지 않습니다. (이 "metafore"의 템플릿 제외.
즉, "정의"를 하위 그룹으로 분할해야합니다.이 경우 두 가지 유형의 정의가 있습니다.
이제 저는 물론 첫 번째 하위 그룹에 대해 이야기하고 있습니다.
헤더는 나머지 소프트웨어가 구현을 사용하도록 돕기 위해 구조의 레이아웃을 정의하기위한 것입니다. 당신은 그것을 당신의 구현의 "추상화"로보고 싶을지도 모릅니다. 이것은 우스꽝스럽게 말하지만, 저는 이것이이 경우에 아주 적합하다고 생각합니다.
이전 포스터에서 개인 및 공용 사용 영역과 헤더를 선언하고 표시했듯이 여기에는 개인 및 공용 변수도 포함됩니다. 이제 여기에서 코드를 디자인하고 싶지는 않지만 헤더에 넣은 내용은 최종 사용자와 구현 사이의 레이어이므로 고려할 수 있습니다.
헤더 (.h)
본문 (.cpp)
경험상 모듈의 "공유"부분은 .h (다른 모듈이 볼 수 있어야하는 부분)에, "공유되지 않음"부분은 .cpp에 배치합니다.
PD : 네, 전역 변수를 포함 시켰습니다. 나는 그것들을 몇 번 사용했고 헤더에 그것들을 정의하지 않는 것이 중요합니다. 그렇지 않으면 여러분은 각각 자체 변수를 정의하는 많은 모듈을 얻게 될 것입니다.
편집 : David의 코멘트 이후 수정