0. 분할되지 않은 기존 코드
→ 세 영역으로 나눌 수 있음
(1) main.cpp 소스파일 (2) func.cpp 파일 (3) struct.h 헤더파일
#include <iostream>
using namespace std;
/* 헤더 파일 */
/*구조체&함수 원형 선언*/
struct MyStruct {
string name;
int age;
};
void display(MyStruct&);
/* 소스 파일 */
/*main 함수*/
int main(){
MyStruct sleepy = {"somuch", 23};
display(sleepy);
return 0;
}
/*함수의 body를 정의*/
void display(MyStruct &refer){
cout << "이름: " << refer.name << endl;
cout << "나이: " << refer.age << endl;
}
1. 헤더 파일 (struct.h)
- #define이나 const를 사용하는 기호 상수
- 구조체 선언
- 클래스 선언
- 템플릿 선언
- 함수 원형 (ex. void display(MyStruct&); 와 같이 원형을 선언해두는 곳이기도 함)
- 인라인 함수
→ reuse하고자 하는 덩어리들의 blueprint를 모아둔 곳
//struct.h
/*ifndef~endif 기호상수화 */
#ifndef STRUCT
#include <iostream>
using namespace std;
/* 헤더 파일 */
/*구조체&함수 원형 선언*/
struct MyStruct {
string name;
int age;
};
void display(MyStruct&);
#endif
ifndef~endif 기호상수화
- STRUCT 덩어리가 이미 include되면, 그다음 같은 것이 호출되는 것을 무시할 수 있음
- 소스파일에서 특정 헤더 파일을 여러 번 호출하는 것이 원래 안 되는데
- 이로 인한 에러가 발생하는 것을 막기 위해, 헤더 파일에 ifndef~endif 구문을 사용함
2. 소스 파일 (main.cpp)
#include "struct.h"
#include "func.cpp"
/* 소스 파일 */
/*main 함수*/
int main(){
MyStruct sleepy = {"somuch", 23};
display(sleepy);
return 0;
}
- #include "struct.h"로 헤더를 반드시 불러와야 함 (전처리기와 관련된 것)
- Any command starting with a # in the first column is not a C/C++ statement, but rather a preprocessor
- Ther preprocessor performs very basic text-based substitutions (간단한 텍스트 대체 기능 수행)
- preprocessor가 처리한 결과물은 compiler로 보내짐
- 헤더파일에서 선언한 함수 / 기호 상수 / 구조체 / 클래스 / 템플릿 / 인라인 함수만이 → main에서 실행될 수 있음
- 실제로 '실행' 대상이 되는 함수
3. 함수 파일 (func.cpp)
//func.cpp
#include "struct.h"
/*함수의 body를 정의*/
void display(MyStruct &refer){
cout << "이름: " << refer.name << endl;
cout << "나이: " << refer.age << endl;
}
- 함수가 정의되어 있는 func.cpp는 마찬가지로, struct.h를 include 해와야 함
- func.cpp와 main.cpp를 직접 연결시키는 코드는 없음. 그러나 문제 없이 작동함.
**업데이트
- 만약 함수 선언을 위한 헤더파일과 & 함수 정의하는 func.cpp를 따로 분리시켰다면, main() 파일에서 func.cpp도 함께 include해야 오류를 방지할 수 있음. 그 이유는, Linker가 func.cpp에서 정의된 함수를 어셈블리 파일에 적절한 위치에 놓아야 하는데, main 파일에 "func.cpp"를 인클루드 한다는 코드가 없다면, 헤더에서 선언한 함수 정의를 찾는 데 문제가 생길 수 있음. (이하와 같은 에러)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
포함시키지 않아도 작동하는 경우가 있지만.. 오류에 대비하는 게 더 좋으니.
#상황
나(programmer): c++로 헤더파일(라이브러리)도 직접 만들었고~ main 소스파일에 불러왔고~ 이제 실행시켜야지~ !
#절차
Programmer: source code <* .cpp>를 작성함
Preprocessor(전처리기): 프로그래머가 작성한 소스코드를 컴파일러에게 전달하기 전, 컴파일 될 수 있는 상태로 준비(전처리)시킴
- 코드를 정리하고 필요한 부분을 추가하거나 변경
- 현재 소스 파일에서 include시킨 헤더 파일을 현재 코드에 포함시킴
- 매크로를 사용하여 특정 코드를 자동으로 대체함 (ex. #define 지시어를 사용하여 상수나 함수 호출을 자동으로 대체)
Compiler: 전처리된 코드를 받아서 실제 기계어로 번역하고 오류가 없는지 확인함.
Linker: 여러 개의 컴파일된 코드파일들을 하나로 합침.
컴파일된 파일과 라이브러리 파일들 간의 상호 의존성을 해결하고, 실행하는 파일의 메모리 주소를 조정함
Linker를 거친 후, 프로그래머가 작성한 코드 파일은 완전히 실행 가능한 상태가 됨~~~~~!~!
'개발 > c++' 카테고리의 다른 글
[c++] this 포인터, 클래스 객체 배열 (0) | 2023.09.08 |
---|---|
[c++] 추상화와 클래스 / 클래스 생성자와 디폴트 생성자 / 클래스 파괴자 (1) | 2023.09.08 |
[c++] 배열과 문자열이 헷갈리지 (1) | 2023.09.07 |
[c++] 함수 템플릿 (0) | 2023.09.07 |
[c++] 함수 오버로딩 (0) | 2023.09.05 |