가급적 선행 처리자보다 컴파일러를 더 가까이 하자.

#define SIZE 10

--> 컴파일러에겐 보이지 않는다. 전처리기가 컴파일러에게 넘어가기 전에 숫자 상수로 대입해 버린다.

--> 기호 테이블에 들어가지 않는다.

--> 에러가 날 경우 SIZE라 표시 되지 않고 10으로 표시 된다 --> 디버깅이 어려움


해결책

const int Size = 10;

--> 매크로 대신 상수를 쓴다.

--> 컴파일러의 눈에도 보이며, 기호테이블에 들어간다.

--> 등장 횟수 만큼 사본을 만드는 매크로와는 달리 단 하나의 원본만 있으면 된다.


tip!!

상수의 정의는 대부분 헤더파일에 넣는다.

ex)

define.h 헤더 파일에 const double Width = 5.4;  정의를 해놓고

  cost double Height = 7.7;  


사용하고자 하는 파일에 가져다가 사용한다.

#include "define.h" 



#define를 상수로 교체할 때 주의점.


1. 상수포인터를 정의하는 경우


const char* const name = "Kim";

const stirng name("Kim");


참고)

1. char* name;    

2. const char* name --> 가리키는 대상을 상수화 시킨다.

3. char* const name --> 포인터 자체를 상수화 시켜 다른 객체를 가리키지 못하게 한다.

4. const char* const name --> 2,3 모두 해당


2. 클래스 멤버로 상수를 정의하는 경우


--> 상수의 유효범위를 클래스 내로 한정하고자 할 때 사용

--> 상수의 사본 개수가 한 개를 넘지 못하게 만들고 싶다면 static멤버로 만든다.


class Cost{

private:

static const int Size;    //  방법 1 : static const int Size = 10 --> 으로 해줄 수도 있으나 지원하지 않는 컴파일러가 있을 수 있다.

int arr[Size];

};

방법 2 : 

const int Cost::Size = 10;  --> static 멤버 초기화 문법 --> main호출 전에 실행된다. 다른 멤버 변수를 이렇게 정의할 수 없다.


====================================================================문제 제기


2번째 방법으로 정의를 해줄 경우 int arr[Size]; 에서 오류가 발생한다.


해결책 --> 나열자 둔갑술 (enum hack)


class Player{

private:

enum { Size = 10 };

int Item[Size];

};

--> 나열자 둔감술은 동작방식이 const보다 #define에 가깝다.

--> const는 주소값을 얻어 낼 수 있지만, enum은 주소값을 얻어낼 수 없다.

--> 따라서 상수를 가지고 주소를 얻는다든지 참조자를 쓴다든지 하는 경우를 방지할 수 있다.

--> enum은 #define처럼 어떤 형태의 쓸모없는 메모리를 할당하지 않는다. --> 그럼 const는 한단 말인가?

--> 나열자 둔갑술은 상당히 상용화된 기술이며 템플릿 메타프로그램의 핵심 기법이다.


클래스 상수를 #define로 만들 경우

--> 유효범위가 없다.

--> 컴파일이 끝날 때까지 유효하다.

--> 캡슐화의 개념이 없다. (private)

--> 따라서 임의의 클래스 안에서만 쓸 수 있는 매크로를 만들 수 없다.


메크로 함수


#define CALL_WITH_MAX (a,b) f((a) > (b) ? (a) : (b))   --> 인자마다 괄호를 씌워주어야 한다.


int main(){

int a = 5;, b = 0;

CALL_WITH_MAX(++a, b);               //a가 두 번 증가   --> 매크로 함수 내에서 a가 두번 불리게 된다.

CALL_WITH_MAX(++a,b+10);          //a가 한 번 증가

}


해결책 --> 인라인함수에 대한 템플릿


template<typename T>

inline void callWithMax(const T& a, const T& b){

f(a > b ? a : b);

}


1. 이 함수는 템플릿이기 때문에 동일 계열 함수군을 만들어낸다.

2. 구현의 어려움 ( 괄호와 같은 )도 없고 인자를 여러번 평가할 (위와 같은 문제) 요소가 사라졌다.

3. 진짜 함수이기 때문에 유효범위 및 접근규칙을 따를 수 있다.


동일 계열 함수군이란?

--> 하나의 템플릿으로 int, double, char 등 여러개의 함수가 만들어 질 수 있다.

      따라서 동일 계열 함수군은 하나의 템플릿으로 만들어 질 수 있는 모든 함수들을 통칭한다.



POINT!!

1. 단순한 상수를 쓸 때는, #define보다 const 객체 혹은 enum을 우선 생각하자.

2. 함수처럼 쓰이는 매크로를 만들려면, #define 보다 인라인 함수를 우선 생각하자.

+ Recent posts