게임학원, 게임프로그래머 취업 전문 교육기관 DirectX11/12 자체엔진 게임개발과정,서버프로그래밍,자료구조,알고리즘,유니티,언리얼 게임학원, 언리얼학원 [Effective C++] #define 보다 const, enum, inline 을 활용해보자
본문 바로가기

[Effective C++] #define 보다 const, enum, inline 을 활용해보자



#define 이란 컴파일 실행 전에 선행 처리자가 먼저 수행함


------>   전처리 문의 종류 링크  <------


#define 의 단점 

 

#define  ASPECT_RATIO  6.25;


컴파일러 입장에서는 ASPECT_RATIO 는 코드 상에서 이미 전부 6.25 로 바뀐 상태

만약 이 부분에서 에러 발생시, 에러메시지 에서는 6.25 로 출력됨.

본인이 ASPECT_RATIO 를 직접 선언하지 않았다면 6.25 가 무엇인지 헷갈릴 수 있음.

 

 

#define 대체방법        

 

1. 컴파일러가 인지하는 상수로 만들어라.

 

const float ASPECT_RATIO = 6.25 ;


주의점)

상수 포인터를 정의할 경우는 타입과 변수 명 앞에 둘 다 const 를 붙인다.

 

const  char* const myName = "Raimondo" ;

문자열의 시작 주소를 통해서 수정을 시도하면 안 된다. 

myName[0] = 'x';  // 런 타임 에러 발생( 코드영역에 있는 문자열을 바꾸려고 시도함 )

myName 의 주소가 가리키는 곳은 "Raimondo" 문자열로 고정.


차라리 위에 경우는 상수 포인터보다 string 객체로 선언 하는 게 더 낫다.

         

const string myName = "Raimondo" ;

         

 

2. 클래스 에서만 상수가 쓰일 경우 상수를 맴버로 선언하라.

class GamePlayer
{
private:
        static const int Numturns = 5 ; 
};

 

클래스 에서 static 변수를 선언하면, 해당 클래스를 쓰는 모든 사본들을 통틀어

최초 1번만 전역적으로 데이터에 저장된다.

 

주의점)

위에 Numturns 는 정의가 아니라 선언이다. static 으로 선언과 동시에 초기화 한 것.

int, char, bool 등의 타입은 위와 같이 선언만으로도 컴파일러가 문제를 제시하지 않는다.


하지만, 클래스 내부 초가화를 허용하는 경우가 정수 타입에만 국한 되어있다.

class GamePlayer
{
private:
    static const double m_PI = 3.14;  // <--에러 : 정적 상수인 정수계열만 내부에서 초기화 가능.
};
 

따라서 실수타입에 대해서는 클래스 상수를 클래스 내부 초기화가 되지 않는다.

즉 실수타입의 상수 맴버를 생성하고 싶으면 선언에서가 아닌 정의에서 초기화 해주어야 한다.

(실수타입이 아니더라도, 주소타입 등의 static 변수들도 다음과 같이 초기화를 한다.)


//GamePlayer.h 파일입니다.

class GamePlayer
{
private:
    static const double m_PI;     //선언에서 초기화 하지 않음.
};
 

 

//GamePlayer.cpp 파일입니다.
const  double  GamePlayer::m_PI = 3.14;        //타입을 다시 재 명시해주고 정의함.
 (타입 재 명시)

 


 

● enum 을 활용하자

class GamepPlayer{
private:
   enum{ Number = 5 };

  
int  m_iArrScore[ Number ];  //enum 값을 접근해서 수정불가. #define 의 상수와 유사함

                                         //score 배열 선언 시에 문제없이 Number의 값을 알고 있음.
};

 

위에 Numberstatic const 로 선언 했을 경우엔 컴파일러가 구식이라면,

m_iArrScore 배열을 선언하는 시점에서 배열의 크기를 알 수 없다고 오류를 낼 수 가 있음.

enum 은 처리시점이 #define 과 유사하므로 안전함.

 

enum 의 또 다른 특징은 바로 보안성.

const 로 선언된 변수의 주소를 취하는 것은 문제가 되지 않지만

enum 으로 선언된 변수의 주소를 취하는 건 불가능하다.

내가 정의한 상수의 주소를 가지고 조작 하는 것이 싫다면 enum 이 좋은 보안역할을 할 것.

  

#define 매크로 함수보다 inline 함수


                #define MAX( a , b ) (a > b) ? a : b


이런 매크로 함수의 경우 다음과 같은 증감 연산자를 이용한 호출을 조심하여야 한다.


        int a = 0;

        int b = 5;

        MAX( a, ++b );


b 가 두 번 증가하게 된다. ++b가 매크로 에서 처리되면서 b가 더 크므로 2번 처리됨.


template<typename T> inline void MAX( const T& a, const T& b)

{
  
T c = (>b) ? a : b;
   cout<< c <<endl;
}
 


MAX
(a , ++b);   //함수로 넘어가는 시점에서 이미 증가된체 함수에서 받으므로 1번 증가한다.

이런 문제를 해결하며 매크로 함수의 효율을 가진 것이 inline 함수이다.

- by Raimondo 


'정보 & 소식 > C, C++' 카테고리의 다른 글

Effective C++<머리말>Effective C++에 대해 포스팅 하겠습니다  (0) 2016.10.19
컴파일과정  (0) 2016.08.06
[Effective C++] 클래스의 생성  (0) 2016.05.18
배열과 포인터  (0) 2016.04.28
포인터와 운영체제  (0) 2016.04.28