안녕하세요
오늘은 C++ 파일분할법에 대해서 공부를 했습니다.
지금까지 저는 'main.cpp' 라는 파일 하나에 작성을 해왔습니다.
물론 틀린 방법은 아닙니다. 하지만 프로그램의 규모가 커지고, 코드의 줄도 길어진다면 가독성이 떨어지지않을까요?
또 다른곳에서 사용을 할 수도 있는 코드는 재사용성이 있으므로, 나누는것이 효율적이라는 생각이 듭니다.
'헤더파일'
'cpp파일'
이렇게 두 종류로 나눌 수 있는데요
header는 단어를 해석하자면, 머리 라는뜻이 있는데요
헤더파일 : 클래스의 선언부, 함수 선언 확장자는 .h
cpp파일 : 클래서의 구현부, 함수 구현 확장자는 .cpp
그렇다면 나누는 법을 알아보도록 하겠습니다.
#include <iostream> class Calculator { public: ~Calculator(){} Calculator() { a = 0; b = 0; result = 0; std::cout << "계산기 생성" << std::endl; } void Add(int x, int y) { a = x; b = y; result = a + b; } void Subtract(int x, int y) { a = x; b = y; result = a - b; } void ShowResult() { std::cout << "result : " << result << std::endl; } private: int a; int b; int result; }; int main() { Calculator c; c.Add(1, 2); c.ShowResult(); c.Subtract(1, 2); c.ShowResult(); }
Calculator 클래스를 예를 들겠습니다.
굳이 저렇게 작성했습니다.
여기서 헤더는 선언부입니다.
선언'만' 하는 부분입니다.
[함수의 선언]
~Calculator(){}
Calculator();
void Add(int x, int y);
void Subtract(int x, int y);
void ShowResult();
[변수의 선언]
int a;
int b;
int result;
그렇다면
헤더파일을 만들어 보겠습니다.
이름은 클래스명과 똑같이 하면 되겠습니다.
그러면 여기서 나오는
#ifndef Calculator_h
#define Calculator_h
#endif
이 뜻이 궁금하실텐데요
if
define
end... if 대충 짐작을 하자면
만약에 ~ 이런뜻인것 같습니다.
정확하게 짚고 넘어가겠습니다.
'#'의 문자열이 붙는다면 이것은 '전처리기' 입니다.
전 처리기의 용어를 보자면 '처리하기 전' 이라는 뜻인데
컴파일이 실행되기 전 명령문 입니다.
ifndef는 무엇인가?
if not defined Calculator_h Calculator_h가정의되어있지않다면
define Calculator_h 를 정의한다.
endif 여기까지
그러면 #define Calculator_h 아래에 코드를 삽입하면 되겠습니다.
이 구문들을 쓰는 이유는 헤더파일이 중복 선언되는걸 막기 위해서입니다.
헤더파일이 중복된다면 이중중복이 되어서 컴파일에러가 날게 분명합니다.
다른 방식은
#pragma once
이후 코드삽입
입니다.
두 구문의 차이를 알아보겠습니다.
#ifndef
#define
#endif
vs
#pragma once
위의 구문은 조건문을 통해 실행여부를 판단하고
아래의 구문은 '이 파일을 한번만 읽어들여라' 라는 뜻입니다.
pragma는 한번만 실행하기에 한번 실행 후에는 열어보지도 않습니다.
당연히 읽어들이기는 하는 #ifndef가 pragma보다 속도가 상대적으로 느린감이 있습니다.
결론은 pragma once 를 사용하는것이 효율적입니다.
다시 본론으로 오면 헤더파일은
Calculaotr.h
선언만 하면 됩니다!!
다음은 cpp입니다
Calculator.cpp
여기서 주의할점은 .cpp파일에
#include "Calculator.h"
를 작성해주셔서 머리를 조립해주시면 됩니다.
그리고 함수명 앞에
클래스명과 scope연산자를 적어주시면됩니다
클래스명::함수명
범위연산자는 이 함수나 변수가 어디로부터 가져오는지 알려주는 역할을 합니다.
그러면 머리와 몸은 완성이 됐습니다.
하지만 코드를 보시면 굉장히 불편한
빨간줄이 그어져있습니다.
이유는
'std'식별자가 정의되어있지 않다 라는 뜻인데요
우리는 기본적으로 main()을 만들면
자동적으로
#include <iostream> 생성이 되었는데요
iostream 은 Input/Output Stream 입출력 c++ 표준 라이브러리 입니다.
cpp파일에 #include <iostream> 을 하면 될까요?
됩니다.
하지만 .cpp는 구현부입니다. 선언은 .h인 헤더파일에 하도록 하겠습니다.
헤더파일에 #include <iostream> 선언!
여기서 또하나의 의문이있습니다.
똑같은 #include 인데
어디서는<> 꺽쇄, 어디서는 "" 큰따옴표 인데요
꺽쇄 <> 를 쓰는 경우 : 꼭 그런것만은 아니지만 보통 컴파일러가 미리 만들어놓은 디렉토리안에서 헤더를 찾습니다. 기존 라이브러리같은경우.
큰따옴표 ""를 쓰는 경우 : #include 를 한 파일과 동일한 디렉토리를 검색합니다. 주로 프로그래머가 직접 정의한 헤더파일을 include할 때 씁니다.
우리는 큰따옴표 ( "" )를 씁니다.
이렇게 완성이 되었습니다.
이제 이것을 main()에서 사용을 하려 한다면
main()에 include 시키면 되겠습니다.
헤더파일만 포함을 시키면 .cpp는 따라옵니다.
main()코드가 한결 깔끔해졌습니다.
헤더파일은 연결시켜주는 '다리(Bridge)' 역할이라고 보시면됩니다.
Calculator.h
- main() 함수호출
- Calculator.cpp 함수구현
이렇게 이어진다고 보시면됩니다.
마지막으로 제가 파일 분할을 하다가 알게 된점입니다.
1. virtual (가상함수) 는 선언부에서 한번만 선언한다.
예를들어
virtual void A()
{
foo
}
라는 함수가있다면
header : virtual void A();
.cpp : void A(){foo}
이렇게 virtual은 한번만 사용하시면 되겠습니다.
2. static은 헤더파일에 선언하고 구현한다.
예를들어
A.h 이라는 헤더파일에
class A
{
public:
static int GetX()
{
foo
}
}
이런식으로 선언과 구현을 동시에 하면 됩니다.
여기까지 파일분할이었습니다.
[알게된 점]
- 파일분할시 virtual과 static의 사용법
- 파일분할방법
- 범위연산자
- #pragma once와 #ifndef 의 차이
[부족한 점]
- 세부적인 컴파일과정
- 어셈블리언어를 배워야 할 것 같다. 배우고싶다.
잘못된점이나 지적 감사하겠습니다!
'복습 > C++' 카테고리의 다른 글
[C++] 복습일지 inline함수 그리고 virtual (0) | 2018.01.24 |
---|---|
[C++] 복습일지 part 2 - 4 #멤버 이니셜라이저 (0) | 2018.01.21 |
[C++] 복습일지 part 2 - 3 #가상함수, 순수가상함수 (0) | 2018.01.14 |
[C++] 복습일지 part 2 - 2 #오버로딩(Overloading)과 오버라이딩(Overriding) (0) | 2018.01.14 |
[C++] 복습일지 part 2 - 1 #상속(Inheritance) (0) | 2018.01.14 |