가급적 선행 처리자보다 컴파일러를 더 가까이 하자.
#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 보다 인라인 함수를 우선 생각하자.
'C++ 심화' 카테고리의 다른 글
[C++] 가상(virtual) 소멸자 (0) | 2016.12.18 |
---|---|
[C++] 컴파일러가 만들어낸 함수가 필요 없을 때 (0) | 2016.12.18 |
[C++] 생성자, 소멸자, 대입 연산자에 주의를 기울이자. (0) | 2016.12.15 |
[C++] 객체의 초기화 (0) | 2016.12.15 |
[C++] const의 활용 (0) | 2016.12.15 |