-
Effective C++...17일지 2022. 6. 18. 14:49
인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자
새로운 타입을 만들어 실수 막기
인터페이스에서 요구하는 특정한 타입이 존재하는 경우 사용자가 실수하더라도 쉽게 그 실수를 인지할 수 있게 된다.
class Date {
public:
Date(int month, int day, int year); // 단순히 int를 사용하는 경우
};
Date(13, 2, 2022); // 입력 순서를 틀리거나
Date(2, 40, 2022); // 존재하지 않는 값을 넘기게 될 수 있다.
위와 같은 경우를 다음과 같이 년, 월, 일을 나타내는 타입을 도입하면 막을 수 있게 된다.
struct Day;
struct Month;
struct Year;class Date {
public:
Date(const& Month month, const& Day day, const& Year year); // 단순히 int를 사용하는 경우
};
Date(30, 3, 1995); // 타입이 맞지 않아 에러 발생
Date(Day(30), Month(3), Year(1995)); // 타입(순서)이 맞지 않아 에러 발생
Date(Month(3), Day(30), Year(1995)); // 정상 동작
추가로 이렇게 타입을 고정시킬 수 있고 입력이 제한되는 경우 미리 값을 정의해 사용할 수 있도록 하여 실수를 막을 수 있다.
class Month {
public:
static Month Jan() { return Month(1); }
static Month Fab() { return Month(2); }
static Month Mar() { return Month(3); }
...
private:
explicit Month(int m); // 외부에서 생성하지 못하도록 막는다.
};
명확한 이유가 없으면 기본 타입의 동작을 따라가자
기본형의 동작은 대부분의 프로그래머가 정확하게 이해하고 있으며 다른 타입도 그렇게 동작하기를 기대한다.
따라서 명확하게 그렇게 동작해야만 하는 게 아니면 기본형 동작을 따라가야 한다.
if (a * b = c) // 이런 동작이 발생하지 않도록 하자
사용자가 무언가 따로 해줘야만 하지 않도록 할 것
기본적으로 사용자는 어떤 동작을 처리하고 다음에 무엇을 해 줘야 하는지 기억을 못 하는 경우가 많다.
따라서 기억하지 않아도 되도록 자동 처리가 되도록 해야한다.
Investment* createInvestment(); // 사용 후 사용자가 자원을 삭제해줘야 하는 구현 대신
std::tr1::shared_ptr<Investment> createInvestment(); // 알아서 자원이 삭제되도록 구현한다.
※ 스마트 포인터 중 shared_ptr을 사용한다면 소멸할 때 특정 함수를 호출하도록 삭제자를 지정할 수 있다.