이유
1. 컴파일러는 선행 처리자를 밀어버리고 숫자 상수로 바꾸어 버리기 때문이다.

#define ASPECT_RATIO 1.653

위와 같이 코드를 썻다고 하면 ASPECT_RATIO 라는이름은 컴파일러가 쓰는 기호 테이블레 들어가지 않는다. 그래서 숫자 상수로 대체된 코드에서 컴파일 에러라도 발생하게 되면 골치가 아플 수 있다. 소스 코드엔 분명히 ASPECT_RATIO가 있었는데 에러 메시지엔 1.653이 있으니 말이다.

해결책

1. 매크로 대신 상수를 사용하자.

const double AspectRatio = 1.653;

AspectRatio는 언어 차원에서 지원하는 상수 타입의 데이터이기 때문에 당연히 컴파일러의 눈에도 보이며 기호 테이블에도 당연히 들어간다. 게다가 상수가 부동소수점 실수 타입일 경우에는 컴파일을 거친 최종 코드의 크기가 #define을 썼을 때보다 작게 나올 수 있다.

#define을 상수로 교체하려면 두 가지 경우만 특별히 조심하자.

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

- 상수 정의는 대게 해더 파일에 넣는 것이 상례이므로 포인터는 꼭 const로 선언해 주어야 하고, 이와 아울러 포인터가 가르키는 대상까지 const로 선언하는 것이 보통이다.

const char* const authorName = "Scott Meyers";

문자열 상수를 쓸 때 위와 같이 char* 기반의 문자열보다는 string 객체가 대체적으로 사용하기 괜찮다.

const std::string myName("Little");


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

어떤 상수의 유효범위를 클래스로 한정하고자 할 때는 그 상수를 멤버로 만들어야 하는데, 그 상수의 사본 개수가 한개를 넘지 못하게 하고 싶다면 정적(static) 멤버로 만들어야 한다.

class GamePlayer {
private:
 static const int NumTurns = 5;     // 상수 선언
 int scores[NumTurns];        // 상수를 사용하는 부분
 ...
}

NumTurns는 '선언(declaration)' 된 것이다. C++에서는 사용하고자 하는 것에 대해 '정의'가 마련되어 있어야 하는게 보통이지만, 정적 멤버로 만들어지는 정수류 타입의 클래스 내부 상수는 예외이다. 이들에 대해 주소를 취하지 않는 한, 정의 없이 선언만 해도 아무 문제가 없게 되어 있다.
단, 클래스 상수의 주소를 구한다든지, 주소를 구하지 않는데도 컴파일러가 정의를 달라고 떼쓰는 경우에는 별도의 정의를 제공해야 한다.

const int GamePlayer::NumTurns;     // NumTurns의 정의.

위의 상수의 정의는 구현 파일에 두어야 한다. 정의에는 상수의 초기값이 있으면 안되는데, 왜냐하면 클래스 상수의 초기값은 해당 상수가 선언된 시점에서 바로 주이지기 때문이다.



2. 클래스를 컴파일하는 도중에 클래스 상수의 값이 필요할 때는 '나열자 둔갑술'을 이용하자.

class GamePlayer {
private:
 enum { NumTurns = 5; };
 int scores[NumTurns];
}

나열자 둔갑술을 알아두면 좋은 이유는 다음과 같다.

2-1. 나열자 둔갑술은 동작 방식이 const보다는 #define에 가깝다. 주소를 얻는다든지 참조자를 쓴다든지 하는 것을 막을 수 있다. enum은 #define처럼 어떤 형태의 쓸데없는 메모리 할당도 절대 저지르지 않는다.


3. #define 을 사용한 매크로 약간의 버그가 있기 때문에 inline 함수에 대한 template을 사용하자.



이것만은 잊지 말자!
- 단순한 상수를 쓸 때는 #define보다 const 객체 혹은 enum을 우선 생각한다.
- 함수처럼 쓰이는 매크로를 만들려면 #define 매크로보다 인라인 함수를 우선 생각한다.


관련 링크
http://ikpil.tistory.com/401
http://ikpil.tistory.com/282
posted by deviAk

초창기의 C++는 단순한 C 언어에 객체 지향 기능 몇 가지가 결합된 형태였으나 꾸준한 성장을 거쳐 아이디어, 기능, 프로그래밍 전략들을 취해 자기 것으로 만드는 데 있어 점점 대담하고 과감한 행보를 보였다.

이렇게 발전한 C++는 다중패러다임 프로그래밍 언어라고 불리운다. 절차적 프로그래밍을 기본으로 객체 지향, 함수식, 일반화 프로그래밍을 포함하여 메타프로그래밍 개념까지 지원하고 있다.

C++를 적절히 사용하기 위해서 C++를 단일 언어로 바라보는 눈을 넓혀, 상관 관계가 있는 여러 언어들의 연합체로 보자. 이렇게 해 가면 시각이 단순해지고 명확해지며, 기억하기도 편해 진다.

C++는 4개의 하위 언어를 제공한다. 제공하는 하위 언어는 다음과 같다.

C : C++는 여전히 C를 기본으로 하고 있다. 블록, 문장, 선행 처리자, 기본제공 데이터타입, 배열, 포인터 등 모든것이 C에서 왔다.

객체 지향 개념의 C++ : '클래스를 쓰는 C'에 관한 것이 모두 해당이 된다. 클래스, 캡슐화 상속, 다형성, 가상 함수 등 객체 지향 설계의 규칙들 대부분이 그대로 있다고 보면 된다.

템플릿 C++ : C+++의 일반화 프로그래밍 부분이다. 템플릿은 완전히 새로운 프로그래밍 패러다임이 파생되었는데 그것을 템플릿 메타프로그래밍(TMP) 라 한다.

STL : STL은 템플릿 라이브러리다. STL은 컨테이너, 반복자, 알고리즘과 함수 객체가 얽혀 돌아가는 것을 규약으로 삼고 있다.

C++는 한 가지 프로그래밍 규칙 아래 똘똘 뭉친 통합 언어가 아니라 네 가지 하위 언어들의 연합체 이다. "하위 언어들로 구성되어 있다" 라는 점을 꼭 새겨 두도록 하자.

이것만은 잊지 말자!
C++를 사용한 효과적인 프로그래밍 규칙은 C++의 어떤 부분을 사용하느냐에 따라 달라진다.


관련 링크
http://ikpil.tistory.com/400
http://jbh5310.springnote.com/pages/702032
http://kelly.springnote.com/pages/552483
posted by deviAk
  • Favicon of https://www.ikpil.com BlogIcon 최익필 2008.05.29 21:50 신고

    C++의 어떤 부분을 이용하느냐에 따라 효과적인 프로그램밍 규칙이 있다. 그래서 C++을 연합체 언어로 바라보는 시각이 필요하다.

    로 요약됬는데, 이건 지금 갖출수 있는 안목이 아닌것 같다.

    1번째 장은 ... 효과적인 C++ 프로그래머로써의 자세를 알려 주는듯!