C++를 언어들의 연합체로 바라보는 안목은 필수
▶ C
▶ 객체 지향 개념의 C+
- 'C with Classes'에 관한 모든 것
- 클래스(Class), 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism). 가상 함수(Virtual function)
- 정적 바인딩: 컴파일시에 메모리를 할당 >> 일반 함수, 일반 변수 할당
- 동적 바인딩: 런타임시에 메모리를 할당 >> 가상 함수, 변수 동적 할당
- https://simsimjae.tistory.com/293
▶ 템플릿 C++
- C++ 일반화 프로그래밍(Generic programming)의 일부
▶ STL
- Standard Template Library
이것만은 잊지 말자!
C++를 사용한 효과적인 프로그래밍 규칙은 경우에 따라 달라진다. 그 경우란, 바로 C++의 어떤 부분을 사용하느냐이다.
#define을 쓰려거든 const, enum, inline을 떠올리자
▶ #define
#define ASPECT_RATIO 1.653
- 컴파일 전에 선행 처리자(Preprocessor)가 ASPECT_RATIO를 찾아 1.653으로 치환함
- 따라서 컴파일러는 이것이 ASPECT_RATIO라는 것을 알 수 없음
- 디버깅에 혼란이 올 수 있음
▶ const
const double AspectRatio = 1.653;
- 위 문제의 해결법은 매크로 대신 상수를 쓰는 것
▶ #define을 상수로 교체할 때 주의점
- 상수 포인터(constant pointer) 정의
- 상수 정의는 대게 헤더 파일에 넣어 다른 파일들이 include해서 사용
- 포인터는 const로 선언하고, 포인터가 가리키는 대상까지 const로 선언
const char* const authorName = "Scott Meyers";
- 클래스 상수 정의
- 클래스 상수의 사본 개수가 1개를 넘지 못하게 하고 싶다면 정적(static) 멤버로 선언
- #define과 달리 클래스 상수는 캡슐화 혜택을 받을 수 있음
- 오래된 컴파일러는 아래 문법을 받아들이지 못하는 경우가 있으므로, 초기값을 상수 정의시 지정
class GamePlayer{
private:
static const int NumTurns = 5; // 클래스 상수 선언과 동시에 초기화
}
// 오래된 컴파일러
class GamePlayer{
private:
static const int NumTurns; // 정적 클래스 상수 선언, 헤더파일
}
const int GamePlayer::NumTurns = 5; // 정적 클래스 상수 정의, 구현 파일
▶ enum
- 컴파일러가 구식인데 클래스를 컴파일하는 도중에 클래스 상수가 필요할 때 사용
- 'enum hack' 기법
- #define처럼 주소를 얻어갈 수 없음
class GamePlayer {
private:
enum { NumTurns = 5 };
int scores[NumTurns];
}
▶ 매크로 함수
- #define을 이용한 매크로 함수는 단점이 많음
- 아래의 경우 비교를 통해 처리한 결과에 따라 a가 증가하는 횟수가 달라짐
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
int a= 5, b = 0;
CALL_WITH_MAX(++a, b); // a가 두 번 증가
CALL_WITH_MAX(++a, b+10); // a가 한 번 증가
- CALL_WITH_MAX(++x, y) → ((++x) > (y) ? (++x) : (y)): 비교할 때 1번, return 할 때 1번 총 2번 증가
- CALL_WITH_MAX(++x, y + 10) → ((++x) > (y + 10) ? (++x) : (y + 10)): 비교할 때 1번 증가
▶ inline
- 매크로 함수의 문제점에 대한 해결법
- 일반적인 함수 호출 과정을 거치지 않고, 함수의 모든 코드를 호출된 자리에 바로 삽입하는 방식
- 함수를 호출하데 걸리는 시간이 절약됨
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
이것만은 잊지 말자!
단순한 상수를 쓸 때는, #define보다 const 객체 혹은 enum을 우선 생각하자
함수처럼 쓰이는 매크로를 만들려면, #define 매크로보다 인라인 함수를 우선 생각하자
낌새만 보이면 const를 들이대 보자!
- 값을 바꾸면 안된다면 명시적으로 const를 사용
char greeting[] = "Hello";
const char *p = greeting; // 비상수 포인터, 상수 데이터
char * const p = greeting; // 상수 포인터, 비상수 데이터
void f1(const Widget *pw);
void f2(Widget const *pw);