C ++로 프로젝트를 작성할 때 파일 세분화 관리가 매우 필요합니다. 오늘 Foxin Technology Channel의 편집자는 C ++의 헤더 파일 및 소스 파일에 대한 자세한 설명을 제공합니다. 이 지식을 배우는 것이 도움이되기를 바랍니다.
C ++의 헤더 파일 및 소스 파일에 대한 자세한 설명
1. C ++ 컴파일 모드
일반적으로 C ++ 프로그램에는 .cpp 파일과 .h 파일의 두 가지 유형이 있습니다. 그 중 .CPP 파일을 C ++ 소스 파일이라고하며 C ++의 소스 코드가 배치됩니다. .H 파일을 C ++ 헤더 파일이라고하고 C ++의 소스 코드가 배치됩니다.
C ++ 언어는 "별도의 컴파일"을 지원합니다. 다시 말해, 프로그램의 모든 내용은 다른 부분으로 나뉘어 다른 .CPP 파일로 배치 될 수 있습니다. .CPP 파일의 물건은 비교적 독립적입니다. 컴파일 (컴파일)시 다른 파일과 통신 할 필요가 없습니다. 대상 파일로 컴파일 한 후에 다른 대상 파일과 링크하면됩니다. 예를 들어, 글로벌 함수 "void a () {}"는 파일 A.CPP에 정의되어 있으며이 기능은 파일 B.CPP에서 호출되어야합니다. 그럼에도 불구하고 A.CPP 및 B.CPP 파일은 서로의 존재를 알 필요가 없지만 별도로 컴파일 할 수 있습니다. 대상 파일로 컴파일 한 후 링크하면 전체 프로그램을 실행할 수 있습니다.
이것은 어떻게 달성됩니까? 프로그램 작성의 관점에서 볼 때 매우 간단합니다. 파일 b.cpp에서 "void a ()"함수를 호출하기 전에 "void a ()"함수를 선언합니다. 첫 번째. 컴파일러가 B.CPP를 컴파일 할 때 심볼 테이블을 생성하기 때문입니다. 볼 수없는 "void a ()"와 같은 기호는이 테이블에 저장됩니다. 다시 연결하면 컴파일러는 다른 객체 파일 에서이 기호의 정의를 찾습니다. 일단 발견되면 프로그램을 원활하게 생성 할 수 있습니다.
여기에 언급 된 두 가지 개념이 있으며, 하나는 "정의"이고 다른 하나는 "선언"입니다. 간단히 말해서, "정의"는 기호를 완전하고 완전한 방식으로 설명하는 것을 의미합니다. 변수 또는 함수, 반환 유형, 필요한 매개 변수 등 "선언"이 기호의 존재를 선언합니다. 즉, 컴파일러가 다른 파일에 정의되어 있음을 알려줍니다. 먼저 사용할 것입니다. 연결하면 다른 곳으로 가서 그것이 무엇인지 알아 내십시오. 정의 할 때 C ++ 구문에 따라 기호 (변수 또는 함수)를 완전히 정의해야하며 선언 할 때이 기호의 프로토 타입 만 작성하면됩니다. 프로그램 내내 기호는 여러 번 기호로 선언 할 수 있지만 한 번만 정의해야합니다. 심볼의 두 가지 다른 정의가 있다면, 컴파일러는 누구를 들어야합니까?
이 메커니즘은 C ++ 프로그래머에게 많은 이점을 제공하며 프로그램 작성 방법으로 이어집니다. 전체 프로그램의 많은 .CPP 파일에서 호출되는 매우 일반적으로 사용되는 기능 "void f () {}"가있는 경우 한 파일 에서이 기능을 정의하고 다른 파일 에서이 기능을 선언하면됩니다. 기능은 처리하기 쉽고, 선언하는 한 문장만을 의미합니다. 그러나 수학적 기능과 같은 기능이 너무 많으면 수백 개의 기능이 있으면 어떨까요? 모든 프로그래머가 모든 기능을 정확하게 기록하고 기록 할 수 있습니까?
2. 헤더 파일이란 무엇입니까?
분명히 대답은 불가능합니다. 그러나 프로그래머가 많은 기능 프로토 타입을 기억하는 데 어려움을 겪는 데 도움이되는 매우 간단한 방법이 있습니다. 먼저 수백 개의 기능의 모든 선언문을 먼저 작성하여 파일에 넣을 수 있습니다. 프로그래머가 필요할 때이 모든 것을 소스 코드로 복사하십시오.
이 방법은 확실히 실현 가능하지만 여전히 너무 귀찮고 서투른 것 같습니다. 따라서 헤더 파일이 그 역할을 수행 할 수 있습니다. 소위 헤더 파일은 실제로 .cpp 파일의 컨텐츠와 동일한 컨텐츠를 가지고 있으며 둘 다 C ++ 소스 코드입니다. 그러나 헤더 파일을 컴파일 할 필요는 없습니다. 모든 함수 선언을 헤더 파일에 넣습니다. .CPP 소스 파일에 필요한 경우, 매크로 명령 "#Include"를 통해이 .CPP 파일에 포함되어 해당 내용이 .CPP 파일로 병합되도록 할 수 있습니다. .CPP 파일이 컴파일되면 포함 된 .H 파일의 기능이 재생됩니다.
예를 들어 봅시다. 모든 수학적 함수에는 F1과 F2가 두 가지만 있다고 가정하면 Math.cpp에 정의를 넣습니다.
/ * math.cpp */double f1 () {// 여기에서 뭔가를합니다 ... return;} double f2 (double a) {// 여기에서 뭔가를합니다 ... a * a}/ * math의 끝 .cpp */헤더 파일 Math.h : "이러한"기능의 선언을 배치하십시오.
/ * math.h */double f1 (); double f2 (double);/ * 수학 끝 .h */
다른 파일 Main.cpp에서는이 두 기능을 호출하고 싶습니다. 헤더 파일 만 포함하면됩니다.
/ * main.cpp */#포함 "math.h"main () {int number1 = f1 (); int number2 = f2 (number1);}/ * main.cpp */이것은 완전한 프로그램입니다. 컴파일러의 명령 후 .H 파일을 작성할 필요는 없지만 컴파일러가 찾을 수있는 장소 (예 : Main.CPP와 동일한 디렉토리)에서 찾을 수있는 장소에서 찾아야합니다. main.cpp 및 math.cpp는 각각 main.o 및 math.o를 생성하도록 컴파일 한 다음이 두 객체 파일을 연결하면 프로그램을 실행할 수 있습니다.
3. #include
#include는 컴파일러가 컴파일되기 전에 작동하는 C 언어의 매크로 명령입니다. #include의 목적은 현재 파일에 작성된 파일의 내용을 완전히 포함하는 것입니다. 다른 기능이나 하위 기능이 없다는 것은 언급 할 가치가 있습니다. 그 기능은 그 뒤에 쓴 파일의 내용으로 나타나는 모든 장소를 교체하는 것입니다. 간단한 텍스트 교체, 다른 것은 없습니다. 따라서 main.cpp 파일의 첫 번째 문장 (#include "math.h")은 컴파일 전에 Math.h 파일의 내용으로 대체됩니다. 즉, 컴파일 프로세스가 시작될 때 main.cpp의 내용이 변경되었습니다.
/ * ~ main.cpp */double f1 (); double f2 (double); main () {int number1 = f1 (); int number2 = f2 (number1);}/ * 끝 ~ main.cpp */더 이상, 옳지 않습니다. 마찬가지로 Main.cpp 외에 F1 및 F2 기능을 사용하는 경우이 두 기능을 사용하기 전에 #include "math.h"만 작성하면됩니다.
4. 헤더 파일로 작성해야 할 사항
위의 논의를 통해 헤더 파일의 기능이 다른 .CPP에 포함되어야한다는 것을 이해할 수 있습니다. 그것들은 컴파일에 참여하지 않지만 실제로는 내용이 여러 .cpp 파일로 컴파일됩니다. "정의는 한 번만 될 수있다"는 규칙을 통해 변수와 함수 선언 만 헤더 파일에 배치해야하며 해당 정의를 배치해서는 안 쉽게 결론을 내릴 수 있습니다. 헤더 파일의 내용은 실제로 여러 다른 .CPP 파일에 도입되므로 모두 컴파일됩니다. 물론 선언을하는 것은 괜찮습니다. 정의를 입력하면 여러 파일에 나타나는 기호 (변수 또는 함수)의 정의와 동일합니다. 이러한 정의는 동일하지만 컴파일러가 그렇게하는 것은 합법적이지 않습니다.
따라서, 당신이 기억해야 할 한 가지는 .h 헤더 파일에 변수 나 함수 선언 만있을 수 있으며 정의를 배치하지 않는다는 것입니다. 즉, 다음과 같은 문장 : Extern Int A; 그리고 void f (); 헤더 파일로만 작성할 수 있습니다. 이것이 진술입니다. int a와 같은 문장을 쓰면; 또는 void f () {}이면 헤더 파일이 둘 이상의 .CPP 파일에 포함되면 컴파일러는 즉시 오류를보고합니다. (외부에 대해서는 이전에 논의되었으며 정의와 선언의 차이는 여기서 논의되지 않을 것입니다.) 그러나이 규칙에는 세 가지 예외가 있습니다.
1. const 객체의 정의는 헤더 파일로 작성할 수 있습니다. Global Const 객체는 기본적으로 외부에 의해 선언되지 않기 때문에 현재 파일에서만 유효합니다. 다른 .CPP 파일에 포함되어 있더라도 이러한 객체를 헤더 파일에 작성하면 객체가 포함 된 파일에서만 유효하며 다른 파일에는 보이지 않으므로 여러 정의로 이어지지 않습니다. 동시에,이 .cpp 파일의 객체는 헤더 파일에서 포함 되므로이 .CPP 파일의 const 객체의 값이 동일하여 하나의 돌로 두 마리의 새를 죽이라고 할 수 있습니다. 마찬가지로 정적 객체의 정의를 헤더 파일에 넣을 수도 있습니다.
2. 인라인 함수의 정의는 헤더 파일로 작성할 수 있습니다. 인라인 함수는 컴파일러가 먼저 선언 한 다음 연결 될 수있는 일반적인 함수가 아니라 (인라인 함수가 연결되지 않음) 정의에 따라 컴파일러가 인라인으로 인라인을 요구하기 때문에 컴파일러는 컴파일 동안 인라인 함수의 완전한 정의를 볼 필요가 있습니다. 인라인 함수를 정상 함수처럼 한 번만 정의 할 수있는 경우 이는 어려울 것입니다. 파일에서는 괜찮으므로 처음에는 인라인 함수의 정의를 쓸 수 있으므로 나중에 사용할 때 정의를 볼 수 있습니다. 그러나 다른 파일 에서이 기능을 사용하면 어떻게됩니까? 이에 대한 좋은 해결책은 거의 없으므로 C ++는 프로그램에서 인라인 함수를 여러 번 정의 할 수 있다고 규정합니다. 인라인 함수가 .cpp 파일에서 한 번만 나타나고 모든 .CPP 파일 에서이 인라인 함수의 정의가 동일하며 컴파일 될 수 있습니다. 그런 다음 분명히 인라인 함수의 정의를 헤더 파일에 넣는 것이 매우 현명합니다.
3. 클래스의 정의는 헤더 파일로 작성할 수 있습니다. 프로그램에서 클래스 객체를 작성할 때 컴파일러는이 클래스의 정의가 완전히 보이면이 클래스의 객체를 어떻게 배치 해야하는지 알 수 있으므로 클래스의 정의에 대한 요구 사항은 기본적으로 인라인 함수와 동일합니다. 따라서 클래스 정의를 헤더 파일에 넣고이 클래스에 사용 된 .CPP 파일에 헤더 파일을 포함시키는 것이 좋습니다. 여기에서 클래스의 정의에는 데이터 구성원 및 기능 구성원이 포함되어 있음을 언급 할 가치가 있습니다. 데이터 구성원은 특정 객체가 생성 될 때까지 (할당 된 공간) 정의되지 않지만 기능 구성원은 처음부터 정의해야합니다. 이는 일반적으로 클래스 구현이라고 부릅니다. 일반적으로 우리의 접근 방식은 클래스 정의를 헤더 파일에 배치하고 기능 멤버의 구현 코드를 .CPP 파일에 넣는 것입니다. 이것은 괜찮고 좋은 방법입니다. 그러나 다른 방법이 있습니다. 이는 기능 코드 멤버를 직접 클래스 정의에 직접 작성하는 것입니다. C ++ 클래스에서 기능 멤버가 클래스 정의 본문에 정의 된 경우 컴파일러는 기능을 인라인으로 간주합니다. 따라서 함수 멤버의 정의를 클래스 정의 본문에 작성하여 헤더 파일로 구성하는 것이 합법적입니다. 기능 멤버가 현재 인라인이 아니기 때문에 클래스 정의의 헤더 파일에 함수 멤버의 정의를 작성하는 것은 불법입니다. 헤더 파일이 두 개 이상의 .CPP 파일에 포함되면이 기능 멤버는 재정의됩니다.
5. 헤더 파일의 보호 조치
헤더 파일에 선언문 만 포함 된 경우, 선언문의 발생이 제한되지 않기 때문에 동일한 .CPP 파일에 여러 번 포함 된 경우 괜찮을 것입니다. 그러나 위에서 설명한 헤더 파일의 세 가지 예외는 헤더 파일의 매우 일반적으로 사용됩니다. 그런 다음 위의 세 가지 예외 중 하나가 헤더 파일에 나타나면 .CPP에 여러 번 포함되면 문제가 커집니다. 이 세 가지 예외의 구문 요소는 "여러 소스 파일에서 정의 될 수있다"는 "한 소스 파일에 한 번만 나타날 수있다". AH가 클래스 A의 정의를 포함하고 BH에 클래스 B의 정의가 포함되어 있다면 클래스 B의 정의는 클래스 A에 따라 달라 지므로 Ah는 BH에서도 #Included입니다. 이제 클래스 A와 클래스 B를 모두 사용하는 소스 파일이 있으므로 프로그래머는이 소스 파일에 AH와 BH를 모두 포함합니다. 현재 문제가 발생합니다.이 소스 파일에 클래스 A의 정의가 두 번 나타납니다! 따라서 전체 프로그램을 컴파일 할 수 없습니다. 당신은 그것이 프로그래머의 실수라고 생각할 수도 있습니다. 그는 BH에 Ah가 포함되어 있다는 것을 알아야합니다. 그러나 실제로 그는해서는 안됩니다.
조건부 편집과 함께 "#Define"을 사용하면이 문제가 해결 될 수 있습니다. 헤더 파일에서 이름은 #define 및 #ifndef를 통해 정의됩니다. #endif는 조건부로 컴파일되어 컴파일러가 이름이 정의되어 있는지에 따라 헤더에서 후속 컨텐츠를 계속 컴파일할지 여부를 결정할 수 있습니다. 이 방법은 간단하지만 헤더 파일을 작성할 때 작성해야합니다.
이 기사를 읽어 주셔서 감사합니다. 이 기사에 소개 된 C ++의 헤더 파일 및 소스 파일에 대한 자세한 설명이 도움이 될 수 있기를 바랍니다. 새로운 기술 채널 네트워크에서 지원해 주셔서 감사합니다!